# TypeScript SDK

Connect your backend with typed resources, asynchronous requests and explicit environments.

## Install

Download `thesauros-sdk-1.1.0.tgz` from [SDK downloads](/sdks/downloads/), then install the file:

```bash
npm install ./thesauros-sdk-1.1.0.tgz
```

This review release has not been published to npm. The package is ESM, requires Node 18+ with `fetch` and has no runtime dependencies. Keep integration credentials on your backend.

## Connect to the Partner API

```ts
import { PartnerClient } from '@thesauros/sdk';

const client = new PartnerClient({
  apiKey: process.env.THESAUROS_API_KEY!,
  base_url: process.env.THESAUROS_API_BASE!,
});

const summary = await client.partner.summary();
console.log(summary.partner.name, summary.as_of);
const history = await client.rates.history('USDC');
console.log(history.scope, history.observations);
```

Use the onboarding URL, including `/api/v1`. An explicit base URL is required. The public developer portal hosts a separate sandbox API. Partner asset identifiers are USDC and USDT0.

## Attribute a customer

```ts
const user = await client.users.create({
  external_id: 'your-partner:customer-1042',
  wallets: ['0x1111111111111111111111111111111111111111'],
});
const positions = await client.partner.userPositions(user.id);
const activity = await client.users.ledger(user.id, { limit: 50 });
```

Replace the example wallet with the customer's address. Namespace the globally unique external ID and retain the returned user ID. Creation is not an upsert. These calls create attribution and read records; they do not deposit customer assets.

## Partner resources

| Resource | Methods |
| --- | --- |
| `partner` | summary, users, deposits, withdrawals, tvl, earnings, points, revenue, userPositions |
| `rates` | history |
| `vaults` | list, history |
| `users` | create, ledger |
| `analytics` | signals, regime, uplift, decisions, advisor |
| `reconciliation` | balances, ledger, snapshots, report |
| `webhooks` | create, list, eventTypes, deliveries, update, delete, test |
| `usage`, `status` | get |
| `keys` | create, list, revoke |
| `partners` | create, list, retrieve, update |
| `campaigns` | create, list, update |

`partner.yieldHistory` remains a deprecated compatibility route; use `rates.history`. Administrative methods require their own scopes. See the [Partner reference](/api/partner/) for exact permissions and parameters.

## Prototype with the sandbox

```ts
import { SandboxClient } from '@thesauros/sdk';

const sandbox = new SandboxClient({
  apiKey: process.env.THESAUROS_SANDBOX_KEY!,
  base_url: process.env.THESAUROS_SANDBOX_BASE!,
});
const position = await sandbox.positions.create({
  wallet: '0x1111111111111111111111111111111111111111',
  asset: 'USDC', amount: 1000,
});
await sandbox.positions.withdraw(position.id, { all: true });
```

Sandbox positions are simulated. Its resources include keys, users, vaults, yield (also `rates`), positions, rebalances, webhooks, analytics, reconciliation, usage and status. `Thesauros` retains the original sandbox client name for existing integrations.

## Responses and errors

Methods return `data`. Read envelope metadata through `client.lastMeta` and HTTP status, request ID and rate-limit headers through `client.lastResponse`. These properties belong to the latest completed request: use a separate client per concurrent workflow when the association matters.

```ts
import { ApiError, NetworkError, RateLimitError } from '@thesauros/sdk';

try {
  const rows = await client.reconciliation.ledger({ limit: 50, offset: 0 });
  console.log(rows.length, client.lastMeta, client.lastResponse?.requestId);
} catch (error) {
  if (error instanceof RateLimitError) console.error(error.retryAfter, error.requestId);
  else if (error instanceof ApiError) console.error(error.status, error.code, error.requestId);
  else if (error instanceof NetworkError) console.error(error.message);
  else throw error;
}
```

Pagination is explicit. The SDK does not automatically traverse additional pages.

## Transport configuration

`timeout` defaults to 30,000 milliseconds per attempt, including response-body reading. `maxRetries` defaults to 3 additional attempts. Only GET requests retry 429 and 5xx with backoff and server retry hints. Network failures and writes are not replayed automatically. Reconcile an uncertain write before sending it again.

Redirects are rejected. Invalid JSON or a missing success envelope raises `ThesaurosError`. The base URL must be absolute HTTP(S) without embedded credentials, query or fragment. The per-attempt timeout does not include waits between retries.

## Verify webhook deliveries

```ts
import { verifyWebhookSignature } from '@thesauros/sdk';

export async function receive(request: Request) {
  const rawBody = new Uint8Array(await request.arrayBuffer());
  const valid = await verifyWebhookSignature(
    process.env.THESAUROS_WEBHOOK_SECRET!,
    request.headers.get('webhook-signature'), rawBody,
    { toleranceSeconds: 300 },
  );
  if (!valid) return new Response('Invalid signature', { status: 400 });
  // Persist the verified event and deduplicate its ID before applying effects.
  return new Response('Accepted', { status: 200 });
}
```

Verification uses Web Crypto HMAC-SHA256 over the original body. Timestamp tolerance is opt-in. The helper does not store replay state: persist and deduplicate event IDs in your receiver. Webhook test methods send a real request to the registered endpoint.

## Build from source

In `sdk/typescript`, run `npm ci`, `npm run build` and `node --test test/*.test.mjs`. The backend's SDK integration suite additionally exercises all 43 Partner methods through the built package against a local database.

Partner types are generated from the verified contract. `PartnerSchemas` and `PartnerQueries` are exported for application types. License: MIT.
