SettleMint
API referenceTypeScript SDK

Install and construct a client

Install the SDK from npm, construct a client against your instance, and choose the credential for where the code runs: a session cookie or an API key.

Overview

A DALP client holds the instance URL, credential, and acting context for API calls. Use a session cookie in a browser and an API key on a server.

An API key grants the access allowed by its scope and the identity it belongs to. A key included in browser or app code is exposed to every user. The SDK rejects an API key when constructing a browser or React Native client.

Install

The SDK is published to npm as @settlemint/dalp-sdk and runs on Node 20 or later, on Bun, in any current browser, and in React Native through Expo SDK 57 (see React Native).

npm install @settlemint/dalp-sdk
pnpm add @settlemint/dalp-sdk
yarn add @settlemint/dalp-sdk

Three peer dependencies are optional and none is installed for you. Add @tanstack/react-query only if you use the query factories; add effect only if you use the Effect surface; add zod only if you use the auth subpath, whose Better Auth client types reference it. A consumer that uses none of the three resolves none of them, and no code in the package imports a schema library at runtime.

Pin the SDK to the same major and minor version as the instance it talks to. The route surface is generated from the instance's own declaration. A client from a later release therefore knows about routes an older instance does not serve, and that failure arrives as a 404 at runtime rather than as a type error at build time.

Construct a client

import { createDalpClient } from "@settlemint/dalp-sdk";

const dalp = createDalpClient({
  baseUrl: "https://your-instance.example.com",
});

const me = await dalp.api.party.users.me();

createDalpClient returns three things:

MemberWhat it is
apiThe namespaced route tree. dalp.api.token.list(), dalp.api.governanceV2.v2.governance.votes.cast({ ... }). This is what most code uses.
executeThe same dispatch reached by route id: dalp.execute("token/list", { page: { limit: 50 } }). For code that builds its own command surface.
conditionalRequestsThe held response-version tags. Call .clear() on sign-out and on an organization switch.

Options

OptionTypeWhat it does
baseUrlstring | URLYour instance's origin. Required. The SDK appends the API mount itself, so pass the origin, not a path under it.
apiKeystring | SecretA server or CLI credential. Rejected when runtime resolves to browser or react-native.
contextDalpClientContextThe acting context, sent as headers on every request. See The acting context.
runtime"browser" | "server" | "react-native"Decides credential rules and cookie behavior. Inferred as react-native when navigator.product is ReactNative, otherwise from whether globalThis.window exists; pass it explicitly wherever that inference is not obviously right.
fetchtypeof fetchYour own fetch. Useful for tests, for a proxy, and for a runtime whose fetch you want to control.
ssrDalpSsrOptionsForwards an incoming request's headers on a server render. See Server-side rendering.
settlementTimeoutMsnumberHow long the platform holds a queue-backed write's response before answering with a 202 handle. A single call may override it. See Mutations.

Choose the credential

Two credentials reach the Platform API, and which one you may use follows from where your code runs rather than from what is convenient.

Session cookie, in a browser

The user signed in and the browser holds the session. Construct the client with no credential at all; it sends the cookie because it runs on your origin. This is what the Console and the Investor portal do.

API key, on a server

A backend service, a scheduled job, a CLI. The key grants its configured access and never leaves your infrastructure. Read it from your secret store, never from a variable your bundler can inline.

In a browser

export const dalp = createDalpClient({
  baseUrl: window.location.origin,
  runtime: "browser",
});

No credential is passed. The client sends credentials with each request, so the session cookie your sign-in established travels automatically, without an API key in the bundle.

Passing an apiKey here throws at construction with a configuration error that names the problem. The refusal is at construction rather than at the first request on purpose. A check that fires only when a request goes out lets a key ship in a bundle and stay quiet until someone exercises that path, which is exactly the case where nobody is watching.

If a key reaches a browser bundle, revoke it on the platform and replace it wherever it is used. Removing it from the next bundle does not invalidate copies already downloaded.

On a server

import { createDalpClient } from "@settlemint/dalp-sdk";

const dalp = createDalpClient({
  baseUrl: process.env.DALP_API_URL!,
  apiKey: process.env.DALP_API_KEY!,
  runtime: "server",
});

Read the key from the environment or a secret manager at runtime. In Next.js, name the variable without the NEXT_PUBLIC_ prefix so the bundler cannot inline it into a client component; in Vite, keep it off the VITE_ prefix for the same reason.

To keep the key out of stack traces and logs, wrap it:

import { createDalpClient, secret } from "@settlemint/dalp-sdk";

const dalp = createDalpClient({
  baseUrl: process.env.DALP_API_URL!,
  apiKey: secret(process.env.DALP_API_KEY!),
  runtime: "server",
});

A Secret prints as a redaction marker wherever something stringifies it, and the SDK unwraps it only at the moment it sets the header. That covers the accidental paths rather than an attacker: a thrown error whose message interpolates the config, a structured log that serializes it, a crash reporter that captures locals. Those are how a server-side key most often reaches a place it should not be, and they are all String(value) under the hood.

The acting context

Most requests also need an acting context: the organization, chain, and signing wallet. The SDK sends this context in request headers.

const dalp = createDalpClient({
  baseUrl,
  runtime: "browser",
  context: {
    organizationId: "org_01J...",
    chainId: 137,
  },
});
FieldHeaderWhen you set it
organizationIdX-Organization-IdWhenever the caller belongs to more than one organization. Almost always.
participantX-ParticipantWhen acting on behalf of a participant rather than as yourself.
executorX-ExecutorTo force a signing route: the caller's own externally owned account, or their smart wallet.
chainIdX-Chain-IdOn a multi-chain instance, to name the EVM network the request speaks to.
selectedSignersX-Selected-SignersOn a multisig write, to name which signers this submission counts toward.
idempotencyKeyIdempotency-KeyRarely at client level. A key is per instruction, not per client, so set it per call.

The context is fixed for the life of the client. When it changes because the user switched organization, build a new client and clear the held response tags. A version tag from the old tenant means nothing under the new one:

dalp.conditionalRequests.clear();

A single call can add headers of its own without rebuilding anything. See Per-call options.

Verify the setup

The cheapest end-to-end check is a read that requires authentication and nothing else:

const me = await dalp.api.party.users.me();
console.log(me.data.id);

A DalpApiError with status 401 means the credential did not arrive. In a browser, the session is missing or expired; on a server, the key is absent or wrong. Status 403 means it arrived and is not permitted to do this, which is a role question rather than a wiring question. Anything else is covered in Errors.

Next

Route calls, paging, and what comes back: Calling routes.

On this page