> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useroutr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK

> The typed client for the Useroutr API, for Node.js 20 and later.

`@useroutr/sdk` is the official client for your server. It is written in TypeScript, ships its
own types, and has no dependencies beyond Useroutr's type package.

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @useroutr/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @useroutr/sdk
  ```

  ```bash yarn theme={null}
  yarn add @useroutr/sdk
  ```

  ```bash bun theme={null}
  bun add @useroutr/sdk
  ```
</CodeGroup>

## Quickstart

```ts theme={null}
import { Useroutr } from "@useroutr/sdk";

const useroutr = new Useroutr({ apiKey: process.env.USEROUTR_API_KEY });

const intent = await useroutr.fundingIntents.create(
  { amount: "25", asset: "asset_usdc_stellar", reference: "ORDER-1042" },
  { idempotencyKey: "ORDER-1042" },
);
```

## Sandbox and production

The key picks the environment, so going live is a change of key and nothing else.

| Key | Calls |
| - | - |
| `ur_test_...` | The sandbox, `https://api.sandbox.useroutr.com`, on the Stellar testnet |
| `ur_live_...` | Production, `https://api.useroutr.com`, on Stellar mainnet |

Each environment refuses the other's keys with a message that says so.

## Options

```ts theme={null}
const useroutr = new Useroutr({
  apiKey: process.env.USEROUTR_API_KEY,
  timeoutMs: 30_000, // per request
  maxRetries: 2, // reads and writes with an idempotency key
  baseUrl: "http://localhost:4000", // only to point somewhere else
});
```

`baseUrl` overrides the key's environment, and so does the `USEROUTR_BASE_URL` environment
variable when `baseUrl` is not given.

## Resources

| Resource | Methods |
| - | - |
| `fundingIntents` | `create`, `retrieve`, `list`, `iterate`, `listPayments`, `retrieveSettlement`, `retrievePublic` |
| `quotes` | `create`, `retrieve`, `list`, `iterate`, `select` |
| `assets` | `list` |
| `payments` | `list`, `iterate`, `listForFundingIntent` |
| `settlements` | `retrieve`, `list`, `iterate`, `retrieveForFundingIntent` |
| `balances` | `list` |
| `ledger` | `list`, `iterate` |
| `refunds` | `create`, `retrieve`, `update` |
| `webhooks.endpoints` | `create`, `retrieve`, `list`, `iterate`, `update`, `delete`, `rotateSecret` |
| `webhooks.events` | `retrieve`, `list`, `iterate` |
| `webhooks.deliveries` | `retrieve`, `list`, `iterate`, `retry` |
| `webhooks` | `constructEvent`, `verifySignature` |
| `requestLogs` | `list`, `iterate`, `retrieve` |
| `applications` | `current`, `retrieve`, `update`, `overview`, `setLogo`, `removeLogo`, `listApiKeys`, `createApiKey`, `revokeApiKey` |

Every method takes a last, optional argument with `idempotencyKey`, `timeoutMs` and `requestId`.
Response types come from `@useroutr/types` and are re-exported by the SDK:

```ts theme={null}
import { type FundingIntentResponse, type WebhookEvent } from "@useroutr/sdk";
```

## Pagination

`list` returns one page. `iterate` walks every page for you:

```ts theme={null}
for await (const intent of useroutr.fundingIntents.iterate({ status: "CREDITED" })) {
  console.log(intent.reference);
}
```

See [Pagination](/integrate/pagination).

## Errors

Every failure is a `UseroutrError` with `code`, `statusCode`, `requestId`, `retryable` and
`details`, and a subclass tells you the kind:

```ts theme={null}
import { UseroutrError, ValidationError } from "@useroutr/sdk";

try {
  await useroutr.fundingIntents.create(params, { idempotencyKey: orderId });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error(error.details);
  } else if (error instanceof UseroutrError && error.retryable) {
    // safe to try again later with the same idempotency key
  } else {
    throw error;
  }
}
```

See [Errors](/integrate/errors) for every class and code.

## Retries and timeouts

Reads, and writes that carry an idempotency key, are retried on `408`, `425`, `429`, `500`,
`502`, `503` and `504`, on timeouts and on connection errors, up to `maxRetries` times, honouring
`Retry-After`. Writes without a key are
never retried, so a network error can never create a duplicate. A timeout surfaces as a
`ConnectionError` with `code: "TIMEOUT"`.

## Webhooks

`constructEvent` verifies the signature and returns the typed event. See
[Webhooks](/guides/webhooks) for complete handlers.

```ts theme={null}
const event = useroutr.webhooks.constructEvent({
  payload: rawBody,
  signatureHeader: headers["useroutr-signature"],
  eventId: headers["useroutr-event-id"],
  secret: process.env.USEROUTR_WEBHOOK_SECRET!,
});
```

## Anything else

`request` calls any endpoint directly and also returns the request id and whether an idempotent
call was replayed:

```ts theme={null}
const { data, requestId, idempotencyReplayed } = await useroutr.request({
  method: "GET",
  path: "/v1/funding-intents",
});
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.