# TypeScript SDK

`@aureahub/sdk`: a typed method for every route these pages document, generated from the live OpenAPI document, with a client that signs your server's calls, sends the user's access token, and throws typed errors. ESM and CommonJS, with type declarations, and no runtime dependencies.

## Overview

- **Every documented route** is a method of the client, grouped as the reference groups them: `aurea.auth`, `aurea.wallets`, `aurea.transactions`, `aurea.swap`, `aurea.cards` (`/v1/cards/*`), `aurea.lending` (`/v1/lending/*`)… The method is named after the route: `GET /v1/wallets/{id}/balance` is `wallets.v1WalletsIdBalanceGet({ id })`.
- **Signing**: the routes that check your tenant's signature are signed for you, exactly as [Authentication › HMAC Request Signing](https://docs.aureahub.com/docs/authentication.md) describes, again on every attempt.
- **Errors**: a refused call throws an error with its `status` and its stable `code` ([Errors & Codes](https://docs.aureahub.com/docs/errors.md)).
- **Retries** only where a retry cannot run anything twice ([Idempotency](https://docs.aureahub.com/docs/idempotency.md), [Rate Limits](https://docs.aureahub.com/docs/rate-limiting.md)).
- Node.js 20 or later, Deno, Bun and edge runtimes: it uses the runtime's `fetch` and Web Crypto. The package: [npm](https://www.npmjs.com/package/@aureahub/sdk).

## Install

```bash
npm install @aureahub/sdk
```

## Quickstart

The six steps of the [Quickstart](https://docs.aureahub.com/docs/quickstart.md), on your server — the API secret never leaves it:

```typescript
import { Aurea, idempotencyKey } from '@aureahub/sdk';

// 1. Your server signs the tenant's calls with your API key and secret
const aurea = new Aurea({
  apiKey: process.env.AUREA_TENANT_API_KEY,
  apiSecret: process.env.AUREA_TENANT_API_SECRET,
});

// 2. Register a test user: the answer signs the user in
const { accessToken } = await aurea.auth.v1AuthRegisterPost({
  v1AuthRegisterPostRequest: { username: 'quickstart_alice', email: 'alice@example.com', password: 'SecurePass123' },
});
const user = aurea.withAccessToken(accessToken!); // every other call uses the user's access token

// 3. A wallet on one of your tenant's test networks
const { chains } = await user.tokens.v1TokensMetaChainsGet({ isTestnet: 'true' });
const wallet = await user.wallets.v1WalletsPost({
  v1WalletsPostRequest: { chain: chains![0].id!, isTestnet: true, name: 'Quickstart' },
});

// 4. Fund wallet.address from a faucet of that test network, then read the balance
const balance = await user.wallets.v1WalletsIdBalanceGet({ id: wallet.id! });

// 5. Send it with a key you keep: a retry with the same key never sends twice
const key = idempotencyKey();
const tx = await user.transactions.v1TransactionsPost({
  idempotencyKey: key,
  v1TransactionsPostRequest: {
    walletId: wallet.id!,
    toAddress: '0x52908400098527886E0F7030069857D2E4169EE7',
    amount: '1000000000000000', // 0.001 of an 18-decimal coin, in the smallest unit
  },
});

// 6. Follow it to the end
const status = await user.transactions.v1TransactionsIdStatusGet({ id: tx.id! });
```

- Amounts you send are integer strings in a token's smallest unit; balances are decimal strings for display ([Amount Units](https://docs.aureahub.com/docs/amounts.md)).
- `withAccessToken()` takes a token or a function that returns a fresh one, called before each call: refresh the token there ([Refresh Token](https://docs.aureahub.com/docs/auth-refresh.md)).
- Each method has a `…Raw` twin that also answers the `Response`, for its headers (`idempotency-replayed`, `X-Request-ID`).

## Request Signing

The client signs the routes listed in [Authentication › Credentials by Route](https://docs.aureahub.com/docs/authentication.md) with the `apiKey` and `apiSecret` you give it. To sign a request you send yourself:

```typescript
import { signRequest } from '@aureahub/sdk';

const body = JSON.stringify({ username: 'alice', password: 'SecurePass123' });
const headers = await signRequest({
  method: 'POST',
  path: '/v1/auth/login',          // with the query string, if any
  body,                            // the exact string you send
  apiKey: process.env.AUREA_TENANT_API_KEY,
  apiSecret: process.env.AUREA_TENANT_API_SECRET,
});
// { 'x-tenant-api-key': …, 'x-timestamp': …, 'x-signature': … }
```

> Warning: The client refuses the API secret in a browser page: anyone who can read the page could sign as your tenant. Your apps call with the signed-in user's access token; your server keeps the secret.

## Errors

```typescript
import { AureaApiError, AureaRateLimitError } from '@aureahub/sdk';

try {
  await user.transactions.v1TransactionsPost({ idempotencyKey: key, v1TransactionsPostRequest: request });
} catch (err) {
  if (err instanceof AureaApiError) {
    err.status;     // branch on this first
    err.code;       // details.code, else code; null when the error has none
    err.details;    // validation problems and ids, when returned
    err.requestId;  // X-Request-ID: quote it to help@aureahub.com
  }
  throw err;
}
```

- One class per kind, all extending `AureaApiError`: `AureaValidationError` (400, 422), `AureaAuthenticationError` (401), `AureaPermissionError` (403), `AureaNotFoundError` (404), `AureaConflictError` (409), `AureaGoneError` (410), `AureaPayloadTooLargeError` (413), `AureaLockedError` (423), `AureaRateLimitError` (429, with `retryAfterSeconds`), `AureaServerError` (5xx).
- On the sign-in routes, whose error bodies keep only `error` and `message`, the code is read from `WWW-Authenticate`.
- `AureaConnectionError`: no answer came (network or timeout) — whether a call that moves funds ran is not known: check before sending it again.

## Idempotency and Retries

Create one key per operation with `idempotencyKey()`, keep it with the pending operation, and send it with every attempt — the money routes take it as `idempotencyKey`. The client retries at most twice by default (`maxRetries`), and only:

- `429`, after `retry-after` seconds;
- `409` `IDEMPOTENCY_IN_PROGRESS`, with the same key, a moment later;
- `502`, `503`, `504` and a request that got no answer — for a `GET`, or for a request with an `Idempotency-Key`.

A `POST` without a key is never sent again; `409` `IDEMPOTENCY_OUTCOME_UNKNOWN`, `423`, `500` and the other `4xx` are never retried. Each attempt is signed again: a signature is accepted once.

## Pagination

One helper per [pagination style](https://docs.aureahub.com/docs/pagination.md), each yielding the items one by one:

```typescript
import { paginateOffset, paginatePages, paginateSkip } from '@aureahub/sdk';

for await (const wallet of paginateOffset((p) => user.wallets.v1WalletsGet(p), { limit: 100 })) { /* limit + offset */ }
for await (const tx of paginatePages((p) => user.transactions.v1TransactionsGet(p), { limit: 100 })) { /* page + limit */ }
for await (const n of paginateSkip((p) => user.notifications.v1NotificationsInboxGet(p))) { /* limit + skip */ }
```

## Calling Any Route

For a route newer than your SDK version, call it by its path: the client still signs it where the signature is checked, sends the access token, retries where it is safe and throws the typed errors.

```typescript
const page = await user.request('GET', '/v1/wallets/', { query: { limit: 50 } });
await user.request('POST', '/v1/transactions/', { body: { walletId, toAddress, amount }, idempotencyKey: key });
```

## Versions

- The SDK is generated from the [OpenAPI document](https://docs.aureahub.com/docs/api-downloads.md) for the routes these pages document, with the neutral names these pages use: the bank ramp's `bankRampStatus`, `bankRampDepositId`…, the EUR account's `eurAccountIban`…, and the `<field>Neutral` values such as `typeNeutral`. Answers carry them once neutral codes are on for your tenant ([Errors & Codes › Neutral Codes](https://docs.aureahub.com/docs/errors.md)).
- It is a `0.x` release: method and type names may change between minor versions. Pin the version you test with.
- Questions or a problem: [help@aureahub.com](mailto:help@aureahub.com), with the request's `X-Request-ID` — we reply within one business day.

## Agent Payments

The Agent Payments widget, its merchant dashboard and a typed client for the commerce routes are a separate package, `@aureahub/agent-pay` ([Agentic Payments](https://docs.aureahub.com/docs/agentic-payments.md)).

---

Web version: https://docs.aureahub.com/#sdk
