The official TypeScript client for the Ralio agentic payment API.
It handles the machine-authentication path end to end — OAuth 2.1
client_credentials with private_key_jwt and DPoP-bound access tokens — so
your integration can talk to an agent without hand-rolling JWT signing, proof
generation, or token refresh.
Scope. This SDK targets autonomous integrations (CI jobs, agent hosts, server-side callers). It authenticates as a credential binding, which can hold the
agents:executeandtransactions:readscopes. Agent and binding management (agents:config) is a human-only operation in the console and is intentionally not part of this SDK.
npm install @ralioco/sdkRequires Node.js 20.19+, 22.13+, or 24+ (matches our toolchain's
engines.node floor). The SDK is ESM-first and ships CommonJS too; types are
bundled.
Ralio's machine path has no shared secrets. Each credential is a P-256 private key that lives on exactly one host:
- The owner mints a one-time registration ticket in the console
(Settings → Credentials → New credential), choosing the target agent and
a scope ceiling. They send you the
ralio-reg-…ticket. - You call
register(...)on the agent host. It generates a keypair locally, submits the public key, and waits until the owner approves the binding in the console. You get back aclientId(cb_…). - From then on,
RalioClientmints and refreshes DPoP-bound access tokens transparently and signs a fresh proof for every request.
See the API authentication guide for the protocol details.
Run this on the host where the integration will live, after the owner sends you a ticket:
import { register } from "@ralioco/sdk";
const binding = await register({
ticket: "ralio-reg-...",
privateKeyPath: "ralio-key.pem", // generated and written here
requestedScopes: ["agents:execute", "transactions:read"],
});
console.log(binding.clientId); // cb_... — store this alongside the keyregister() resolves once the owner approves (or rejects with a
RalioRegistrationError if the binding is rejected / expires / times out). The
private key never leaves the host.
import { RalioClient } from "@ralioco/sdk";
const client = await RalioClient.create({
clientId: "cb_...",
privateKeyPath: "ralio-key.pem",
});
// One-shot chat — agentId is resolved automatically for a single-agent
// credential; pass agentId explicitly to target one of several agents.
const reply = await client.chat.send({
message: "What is my current balance?",
});
console.log(reply.reply);
// Streaming chat (server-sent events)
for await (const event of client.chat.stream({
message: "List my recent payments",
})) {
if (event.event === "text_delta") {
process.stdout.write(event.text);
} else if (event.event === "tool_started") {
console.log(`\n[tool] ${event.data.tool_name}`);
}
}
// Transactions
const txns = await client.transactions.list({ limit: 20 });
for (const txn of txns) {
console.log(txn.date, txn.amount, txn.currency, txn.creditor, txn.status);
}RalioClient also implements Symbol.dispose, so under using it is released
automatically:
using client = await RalioClient.create({ clientId: "cb_...", privateKeyPath: "ralio-key.pem" });There is no payments.create() method by design. Payments are executed by the
agent, not by direct REST calls: drive the agent with chat.send /
chat.stream ("Pay £500 to Bob for the April invoice") and it will create the
payment, subject to its spend limits and approval rules. Use
transactions.list to read what the agent did.
All errors subclass RalioError:
| Class | When |
|---|---|
RalioAuthError (401) |
Missing/invalid token, failed assertion, or rejected DPoP proof |
RalioPermissionError (403) |
Token lacks the required scope, or resource not owned |
RalioNotFoundError (404) |
Resource doesn't exist |
RalioValidationError (422) |
Invalid field values or business-rule violation |
RalioRateLimitError (429) |
Rate limited — back off and retry |
RalioAPIError |
Any other HTTP error (carries statusCode, detail) |
RalioRegistrationError |
Registration rejected, expired, or timed out |
RalioConfigError |
Local configuration problem |
import { RalioPermissionError } from "@ralioco/sdk";
try {
await client.chat.send({ agentId: "...", message: "..." });
} catch (err) {
if (err instanceof RalioPermissionError) {
console.error("scope problem:", err.detail);
} else {
throw err;
}
}npm install
npm run lint
npm run typecheck
npm test
npm run buildMIT — see LICENSE.