§ SDK · Node.js
Integrate with @nuvouch/node
Use the official SDK when you want typed payloads, predictable error objects, and webhook utilities without manually wiring request signing or parsing.
install
npmnpm install @nuvouch/nodebootstrap.ts
from envimport { Nuvouch } from "@nuvouch/node";
const nuvouch = new Nuvouch({
apiKey: process.env.NUVOUCH_API_KEY,
});
// reads NUVOUCH_API_KEY§ SDK · Connections
Link business subjects once, then reuse them
New integrations should link the subject once, then keep the subject and source mapping stable in your own product. Use the same approved recipient and origin for future requests instead of inventing a new identity each time.
create-connection-session.ts
sdkimport { Nuvouch } from "@nuvouch/node";
const nuvouch = new Nuvouch({ apiKey: process.env.NUVOUCH_API_KEY });
const link = await nuvouch.links.create({
subject: {
id: "cus_123",
label: "Ada Lovelace",
},
source: {
key: "merchant:acct_live_001",
name: "Stripe Live Account",
},
});
console.log(link.id, link.url, link.shortCode);§ SDK · Connection lifecycle
Inspect and revoke existing connections
Fetch session state
get-connection-session.ts
const link = await nuvouch.links.retrieve("conn_sess_123");
console.log(link.status);
console.log(link.connection?.id);Lookup the active link for a subject tuple
lookup-connection.ts
const result = await nuvouch.connections.lookup({
subjectId: "cus_123",
sourceKey: "merchant:acct_live_001",
});
console.log(result?.nuvouchUserId);List connections with filters
list-connections.ts
const result = await nuvouch.connections.list({
subjectId: "cus_123",
status: "active",
});
console.log(result.data.map((item) => item.id));Revoke a link
revoke-connection.ts
const result = await nuvouch.connections.revoke("conn_123");
console.log(result.status); // revoked§ SDK · Approvals
Create a payment authorization request
POST/v1/approvals
create-approval.ts
SDKconst approval = await nuvouch.approvals.create({
subject: {
id: "user_123"
},
source: {
key: "stripe:acct_123",
name: "Stripe"
},
action: {
type: "payment.authorization",
title: "Approve payment",
description: "Allow Billing Agent to charge $84.00"
},
amount: {
value: 84.0,
currency: "USD"
},
details: [
{ label: "Merchant", value: "OpenAI API" },
{ label: "Billing period", value: "April 2026" }
],
actor: {
type: "ai_agent",
name: "Billing Agent"
},
risk: {
level: "medium",
signals: ["automated_action", "usage_threshold_exceeded"]
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" }
],
metadata: {
orderId: "ord_123"
}
});§ SDK · Request lifecycle
Read or cancel request state
Fetch by request id
get.ts
const current = await nuvouch.approvals.retrieve("req_2f5cd6dbb6784b9ab2f7");
console.log(current.status); // pending | approved | denied | expired | cancelledFetch by your external id
get-by-external.ts
const current = await nuvouch.approvals.retrieveByExternalId("payment_auth_001");Cancel a pending request
cancel.ts
const cancelled = await nuvouch.approvals.cancel("req_2f5cd6dbb6784b9ab2f7");§ SDK · Agent Auth
Use the dedicated Agent Auth references
The Node SDK includes Agent Auth runtime and provider helpers, but the full direct runtime flow now lives in the AI Agent Auth reference. Keep this SDK page focused on approvals, links, webhooks, and general client setup.
| Field | Type | Description |
|---|---|---|
| /docs/agent-auth | direct runtime | Runtime-generated QR pairing, delegation request/wait/token, provider introspection, final approval, and CLI usage. |
| /docs/mcp | hosted MCP | Official OAuth-protected MCP discovery, registration, authorization, token, pairing, and MCP delegation tools. |
§ SDK · Reliability
Error and retry behavior
| Field | Type | Description |
|---|---|---|
| NuvouchApiError | error class | Thrown for all non-2xx responses. |
| status | number | HTTP status from the API response. |
| code | string | Stable machine-readable Nuvouch error code when provided. |
| retryAfterSeconds | number | Parsed from Retry-After for rate-limited requests. |
error-handling.ts
import {
NuvouchApiError,
isRateLimitError,
isRetryableError,
} from "@nuvouch/node";
const input = {
subject: {
id: "user_123",
},
source: {
key: "stripe:acct_123",
},
action: {
type: "payment.authorization",
title: "Approve payment",
description: "Allow Billing Agent to charge $84.00",
},
amount: {
value: 84.0,
currency: "USD",
},
actor: {
type: "ai_agent",
name: "Billing Agent",
},
risk: {
level: "medium",
signals: ["automated_action", "usage_threshold_exceeded"],
},
decisions: [
{ label: "Approve", value: "approve" },
{ label: "Deny", value: "deny" }
],
externalRequestId: "payment_auth_001"
};
try {
await nuvouch.approvals.create(input, {
idempotencyKey: "worker_retry_payment_auth_001",
});
} catch (error) {
if (isRateLimitError(error)) {
return;
}
if (
error instanceof NuvouchApiError &&
error.code === "DUPLICATE_EXTERNAL_ID"
) {
return nuvouch.approvals.retrieveByExternalId("payment_auth_001");
}
if (error instanceof NuvouchApiError) {
console.error(error.code, error.status, error.message);
}
if (!isRetryableError(error)) return;
}§ SDK · Webhooks
Verify signed callbacks
callback-handler.ts
import { Nuvouch } from "@nuvouch/node";
const nuvouch = new Nuvouch({ apiKey: process.env.NUVOUCH_API_KEY });
const seenDeliveries = new Set<string>();
export async function handleNuvouchWebhook(req: Request) {
const rawBody = await req.text();
const event = nuvouch.webhooks.verify({
rawBody,
signature: req.headers.get("x-nuvouch-signature"),
secret: process.env.NUVOUCH_CALLBACK_SECRET!,
});
const deliveryId = req.headers.get("x-nuvouch-delivery");
if (deliveryId && seenDeliveries.has(deliveryId)) {
return new Response("duplicate", { status: 200 });
}
if (deliveryId) seenDeliveries.add(deliveryId);
if (nuvouch.webhooks.isApprovalEvent(event) && event.type === "nuvouch.approval_request.approved") {
// commit payment capture side effects exactly once
}
if (nuvouch.webhooks.isConnectionEvent(event) && event.type === "nuvouch.connection.accepted") {
// mark subject tuple as linked in your system
}
return new Response("ok");
}Use a secret manager instead of env vars
callback-handler-secret-manager.ts
import { Nuvouch } from "@nuvouch/node";
const nuvouch = new Nuvouch({ apiKey: process.env.NUVOUCH_API_KEY });
export async function handleNuvouchWebhook(req: Request) {
const rawBody = await req.text();
const callbackSecret = await secrets.get("integrations/nuvouch/callback-secret");
const event = nuvouch.webhooks.verify({
secret: callbackSecret,
rawBody,
signature: req.headers.get("x-nuvouch-signature"),
});
console.log("Verified event:", event.type, event.deliveryId);
return new Response("ok");
}Continue with the raw webhook contract on webhook reference.