# TypeScript SDK

The FervusAI TypeScript SDK is the recommended way to integrate with FervusAI from Node.js and TypeScript projects. It covers the full API surface and handles authentication, retries, and error typing.

***

## Installation

```bash
npm install @fervusai/sdk
```

Requires Node.js 18 or later. The SDK is fully typed - no `@types` package needed.

***

## Initialisation

```typescript
import { FervusAI } from "@fervusai/sdk";

const client = new FervusAI({
  apiKey: process.env.FERVUS_API_KEY,
});
```

**Options**

| Option       | Type   | Default                      | Description                                             |
| ------------ | ------ | ---------------------------- | ------------------------------------------------------- |
| `apiKey`     | string | required                     | Your FervusAI API key                                   |
| `baseUrl`    | string | `"https://api.fervus.ai/v1"` | Override for testing against a local mock server        |
| `timeout`    | number | `30000`                      | Request timeout in milliseconds                         |
| `maxRetries` | number | `3`                          | Number of retries on network failure or `5xx` responses |

***

## Wallets

```typescript
// Create
const wallet = await client.wallets.create({
  agentId: "agent_research_v2",
  label: "Research Agent - Market Data",
  policyId: "pol_conservative",
  tags: ["research", "production"],
});

// Get
const wallet = await client.wallets.get("wal_9f3a2b");

// List
const { data, hasMore, nextCursor } = await client.wallets.list({
  status: "active",
  tags: ["production"],
  limit: 50,
});

// Update
await client.wallets.update("wal_9f3a2b", {
  label: "Research Agent v2",
  policyId: "pol_conservative_strict",
});

// Freeze / Unfreeze
await client.wallets.update("wal_9f3a2b", { status: "frozen" });
await client.wallets.update("wal_9f3a2b", { status: "active" });

// Fund
await client.wallets.fund({ walletId: "wal_9f3a2b", amount: "100.00", currency: "USDC" });

// Fund batch
await client.wallets.fundBatch([
  { walletId: "wal_9f3a2b", amount: "100.00" },
  { walletId: "wal_7d1e4c", amount: "250.00" },
]);

// Withdraw
await client.wallets.withdraw({ walletId: "wal_9f3a2b", amount: "50.00" });
await client.wallets.withdraw({ walletId: "wal_9f3a2b", amount: "all" });

// Auto-topup
await client.wallets.setAutoTopup("wal_9f3a2b", {
  enabled: true,
  triggerBelow: "10.00",
  topupAmount: "50.00",
});

// Rotate session token
const { sessionToken, expiresAt } = await client.wallets.rotateToken("wal_9f3a2b", {
  ttlSeconds: 3600,
});

// Archive
await client.wallets.archive("wal_9f3a2b");
```

### Wallet instance methods

After fetching or creating a wallet, you can call payment and transaction methods directly on the wallet object:

```typescript
const wallet = await client.wallets.get("wal_9f3a2b");

// Pay
const tx = await wallet.pay({
  to: "api.perplexity.ai",
  amount: "2.50",
  currency: "USDC",
  memo: "Query batch #8821",
});

// Balance
const balance = await wallet.balance();
// "97.50"

// Transaction history
const { data } = await wallet.transactions.list({ limit: 50 });
```

***

## Policies

```typescript
// Create
const policy = await client.policies.create({
  name: "Conservative - Research Agent",
  maxPerTx: "5.00",
  maxPerDay: "50.00",
  maxPerMonth: "500.00",
  velocityCap: 20,
  allowedRecipients: ["api.perplexity.ai"],
});

// Get
const policy = await client.policies.get("pol_7a2c4e");

// List
const { data } = await client.policies.list();

// Update
await client.policies.update("pol_7a2c4e", { maxPerDay: "75.00" });

// Clone
const newPolicy = await client.policies.clone("pol_conservative", {
  name: "Conservative + Perplexity only",
  allowedRecipients: ["api.perplexity.ai"],
});

// Audit log
const { data } = await client.policies.auditLog("pol_7a2c4e");

// Delete
await client.policies.delete("pol_7a2c4e");
```

***

## Payments

```typescript
// Standard payment
const tx = await client.payments.create({
  walletId: "wal_9f3a2b",
  to: "api.perplexity.ai",
  amount: "2.50",
  currency: "USDC",
  memo: "Query batch #8821",
  idempotencyKey: "batch_8821_pay",
});

// Get payment
const tx = await client.payments.get("tx_4f7c1a");
```

### A2A payments

```typescript
// Create escrow
const escrow = await client.payments.a2a.create({
  fromWallet: "wal_requester",
  toWallet: "7xKp...nR4Q",
  amount: "10.00",
  currency: "USDC",
  taskDescription: "Summarise Q1 2026 earnings calls - healthcare sector",
  timeoutSeconds: 3600,
});

// Complete escrow
await client.payments.a2a.complete("escrow_xyz", {
  proofType: "output_hash",
  proof: "sha256:a3f2b1c4...",
});

// Dispute escrow
await client.payments.a2a.dispute("escrow_xyz", {
  reason: "Output does not match specification",
  evidence: "sha256:evidence_hash...",
});

// Get escrow
const escrow = await client.payments.a2a.get("escrow_xyz");

// List escrows
const { data } = await client.payments.a2a.list({
  walletId: "wal_requester",
  status: "locked",
});
```

***

## Transactions

```typescript
// Get
const tx = await client.transactions.get("tx_4f7c1a");

// List (all wallets)
const { data } = await client.transactions.list({
  status: "confirmed",
  from: "2026-04-01T00:00:00Z",
  to: "2026-04-30T23:59:59Z",
  limit: 100,
});

// List (single wallet)
const { data } = await client.wallets.transactions.list("wal_9f3a2b", {
  limit: 50,
});

// Export
const exportJob = await client.transactions.export({
  format: "csv",
  walletId: "wal_9f3a2b",
  from: "2026-04-01T00:00:00Z",
  to: "2026-04-30T23:59:59Z",
});
```

***

## Webhooks

```typescript
// Create
const webhook = await client.webhooks.create({
  url: "https://your-server.com/fervus-events",
  events: ["transaction.completed", "transaction.blocked", "balance.low"],
});

// Test
await client.webhooks.test("wh_7b3f1e");

// List
const { data } = await client.webhooks.list();

// Update
await client.webhooks.update("wh_7b3f1e", {
  events: ["*"],
});

// Delete
await client.webhooks.delete("wh_7b3f1e");
```

### Signature verification helper

```typescript
import { FervusAI } from "@fervusai/sdk";

const isValid = FervusAI.verifyWebhookSignature({
  rawBody: req.body.toString(),
  signature: req.headers["fervus-signature"] as string,
  secret: process.env.WEBHOOK_SECRET!,
});
```

***

## Error handling

```typescript
import { FervusAI, FervusAIError, PolicyViolationError, NotFoundError } from "@fervusai/sdk";

try {
  const tx = await wallet.pay({ to: "api.perplexity.ai", amount: "50.00", currency: "USDC" });
} catch (err) {
  if (err instanceof PolicyViolationError) {
    // err.violation: { rule, limit, attempted }
  } else if (err instanceof NotFoundError) {
    // Wallet, policy, or transaction does not exist
  } else if (err instanceof FervusAIError) {
    // err.code, err.message, err.requestId, err.statusCode
  }
}
```

***

## Pagination

All list methods return `{ data, hasMore, nextCursor }`. Use the `nextCursor` to fetch subsequent pages:

```typescript
let cursor: string | undefined;

do {
  const result = await client.wallets.list({ limit: 100, cursor });
  for (const wallet of result.data) {
    // process wallet
  }
  cursor = result.nextCursor;
} while (result.hasMore);
```

Or use the built-in async iterator:

```typescript
for await (const wallet of client.wallets.iterate({ status: "active" })) {
  // process wallet - pages automatically
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fervusai.com/sdk/typescript.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
