Calling routes
Every route is a node on one namespaced tree, called with one flat object the SDK splits into path, query, and body, returning the response envelope unchanged.
Overview
The SDK maps route identifiers to a namespaced client. GET /tokens is dalp.api.token.list(). POST /tokens/{assetId}/transfers is dalp.api.token.transfer({ assetId, transfers }). The client uses the routes included in its installed SDK version.
A call takes one flat argument and returns the response envelope. The SDK also supports conditional reads and cancellation. Mutations and settlement covers writes and retries.
One flat argument
Each call takes one object:
await dalp.api.token.transfer({
assetId: "0x1234...",
transfers: [{ recipient: "0xabcd...", amount: "1000" }],
});The route declaration identifies the path parameters. The SDK puts assetId in the URL and the remaining input in the body. On a GET, HEAD, or DELETE, the remaining input becomes query parameters. The call uses the same flat input shape.
How one flat object becomes a request: the declaration's path template decides which keys go in the URL, and the method decides whether the rest form a query string or a body.
A route with no required input takes no argument at all:
const me = await dalp.api.party.users.me();
const tokens = await dalp.api.token.list();A missing path parameter throws a TypeError at the call, naming the parameter and the route, rather than sending a request to a URL with a literal :assetId in it.
The generated route table rejects ambiguous path, query, or body keys.
Discovering routes
In an editor, dalp.api. lists the namespaces. Each namespace lists its operations, and each operation shows its request and response types.
A namespace can also be an operation. dalp.api.token.read is a call, and routes that sit beneath it are still reachable as properties on the same node, so a path being both a route and a prefix is not a conflict you have to work around.
When you are building a command surface of your own and hold a route id as a string rather than a path, use execute:
const result = await dalp.execute("token/list", { page: { limit: 50 } });It is the same dispatch, the same transport, and the same errors. An unknown route id throws a TypeError naming it. Import the route table to enumerate the routes in your installed SDK:
import { routeTable } from "@settlemint/dalp-sdk/routes";
const routeIds = Object.keys(routeTable.routes);What comes back
The platform's response envelope, unchanged. A single-resource read resolves to { data, links }; a collection resolves to { data, meta, links }.
const tokens = await dalp.api.token.list({ page: { limit: 50 } });
tokens.data; // the rows
tokens.meta.total; // how many exist in total, not how many came back
tokens.links.next; // the next page's URL, or null on the last pageThe SDK returns the full envelope with compile-time response types. It also checks each success response against the route's declared response, and a body that does not match throws sdk.response.MALFORMED_SUCCESS rather than reaching your code.
Keep meta.total and links.next when handling a collection. They describe pagination; the returned row count alone does not identify the last page.
A non-2xx response throws rather than resolving. That is covered under Errors.
Paging and filtering
Collection routes take the same parameters the API documents: sort, a page object with limit and offset, and a filter object. Prefix the sort field with - to sort descending.
const page = await dalp.api.token.list({
sort: "name",
page: { limit: 50, offset: 0 },
});The flat keys limit, offset, sortBy, sortDirection, and filters are not part of the client's types, so passing one fails to compile. The API refuses them with a 400.
To walk every page, follow meta.total rather than guessing from the row count, because a page shorter than limit is not by itself the last page:
const rows = [];
let offset = 0;
for (;;) {
const page = await dalp.api.token.list({ page: { limit: 100, offset } });
rows.push(...page.data);
if (rows.length >= page.meta.total) break;
offset += 100;
}A collection can change while you page through it, so offset pagination can repeat or omit rows. Filter to a stable range when consistency matters. Narrow large result sets to limit request volume. Pagination defines the query parameters.
Conditional reads
The SDK holds the version tag the platform returns on a cacheable read, sends it back on the next read of the same resource, and turns an unchanged answer back into the cached body. You get a normal response object either way; an unchanged response transfers no response body.
This is on by default and needs no configuration. What it does need is one call at two moments: on sign-out and on an organization switch.
dalp.conditionalRequests.clear();A version tag identifies a response as seen by one identity acting for one tenant. Carrying tags across a change of either is how a client serves one tenant's cached rows to another, so treat the clear as part of the switch rather than as tidy-up afterwards.
Per-call options
The second argument to any call is options.
await dalp.api.token.list({ page: { limit: 50 } }, { signal: controller.signal });| Option | Type | What it does |
|---|---|---|
signal | AbortSignal | Cancels the request. On a settled write it also stops the wait. |
headers | Record<string, string> or a function returning one | Extra headers for this call. A function is evaluated per request. |
settlementTimeoutMs | number | How long the platform holds this write's response before answering with a 202 handle. Ignored on a read. |
Use the same Idempotency-Key when retrying one instruction. Generate a new key only for a new instruction. A header function runs for each request; keep a retry key outside that function. See Retry safety.
Cancellation
Pass an AbortSignal and the request aborts with it. In React, wire it to the effect's cleanup, or let the TanStack Query factories do it for you, since they pass the query's own signal through.
const controller = new AbortController();
const promise = dalp.api.token.list({ page: { limit: 50 } }, { signal: controller.signal });
controller.abort();An aborted request rejects with the abort reason rather than a DalpApiError, because nothing came back from the platform to build one from.
Next
Writes, retry safety, and settlement: Mutations and settlement.
Install and configure
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.
Mutations and settlement
A write that touches the chain returns the settled resource or the platform's 202 handle; retry safety, the acting context, and errors are yours to handle.