Node.js Integration
Accept crypto payments in Node.js and TypeScript apps
Node.js Integration
Install the official Plaidly Node SDK:
Not yet published to the package registry
@plaidly/node is not yet published to npm — install from source until registry publication ships.
git clone https://github.com/plaidly/plaidly-node.git
cd plaidly-node
npm install
npm run buildOnce published, the intended install command will be:
npm install @plaidly/nodeInitialize the client
import {
PlaidlyClient,
constructWebhookEvent,
constructWebhookEventWithSecrets,
onboardSandboxWithSimulation,
} from '@plaidly/node';
const plaidly = new PlaidlyClient({ apiKey: process.env.PLAIDLY_API_KEY! });Create and poll a payment session
const session = await plaidly.paymentSessions.create({
amount: 10,
expires_in: '15m',
paymentMethod: {
methodID: 0,
chain: 'solana',
token: 'USDC',
network: 'mainnet',
},
metadata: { order_id: 'ord_123' },
});
console.log(session.address);
const latest = await plaidly.paymentSessions.get(session.session_id);
console.log(latest.status);Sandbox onboarding
const publicClient = new PlaidlyClient();
const merchant = await publicClient.merchants.register({
name: 'Acme Demo Store',
webhook_url: process.env.PLAIDLY_WEBHOOK_URL!,
});
const merchantClient = new PlaidlyClient({ apiKey: merchant.api_key });
const flow = await onboardSandboxWithSimulation(
merchantClient,
{ chain: 'solana', token: 'USDC', network: 'testnet' },
{ simulate: true, includeReceipt: true },
);
console.log(flow.demoSession.session_id);
console.log(flow.terminalSession.status);
console.log(flow.receipt?.size ?? 0);Verify webhooks
Express
import express from 'express';
import { constructWebhookEventWithSecrets } from '@plaidly/node';
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-plaidly-signature'] as string;
try {
const event = constructWebhookEventWithSecrets(req.body, signature, [
process.env.PLAIDLY_WEBHOOK_SECRET_NEW!,
process.env.PLAIDLY_WEBHOOK_SECRET_OLD!,
]);
if (event.event_type === 'payment_session.completed') {
fulfillOrder(event.session_id);
}
} catch {
return res.status(400).send('Invalid signature');
}
res.sendStatus(200);
});Next.js App Router
import { constructWebhookEvent } from '@plaidly/node';
import { NextRequest } from 'next/server';
export async function POST(req: NextRequest) {
const rawBody = await req.text();
const signature = req.headers.get('x-plaidly-signature') ?? '';
try {
const event = constructWebhookEvent(
rawBody,
signature,
process.env.PLAIDLY_WEBHOOK_SECRET!,
);
if (event.event_type === 'payment_session.completed') {
await fulfillOrder(event.session_id);
}
} catch {
return new Response('Invalid signature', { status: 400 });
}
return new Response('OK');
}Error handling
The SDK throws typed errors:
import { PlaidlyError } from '@plaidly/node';
try {
await plaidly.paymentSessions.create({
amount: 10,
expires_in: '15m',
paymentMethod: { methodID: 0, chain: 'solana', token: 'USDC', network: 'mainnet' },
});
} catch (err) {
if (err instanceof PlaidlyError) {
console.error(err.code, err.message, err.statusCode);
}
}Agent example flows
The TypeScript example index in plaidly-node/examples/ shows the same flows used by the agent docs:
- sandbox merchant registration plus demo session simulation
- webhook verification with a secret rotation window
- x402 paid-resource retry using the built-in helpers