Loading...
Loading...
Getting started
From zero to a working integration. Each step builds on the last, mark them complete as you go and your progress saves automatically.
Add Payvra to your project. Pick your language above, the install command and every code example on this page will update.
# Install via npm (or yarn / pnpm)npm install payvra# Verify it installednode -e "console.log(require('payvra').VERSION)"Log into the Payvra dashboard and generate a test-mode API key. Test keys start with sk_test_ and only work against the sandbox, no real funds are ever moved.
Open Dashboard// Your test key looks like this:// sk_test_abc123...// Set it as an environment variable:// export PAYVRA_TEST_KEY=sk_test_abc123...import { Payvra } from "payvra";const payvra = new Payvra(process.env.PAYVRA_TEST_KEY!);// Verify your key worksconst keys = await payvra.apiKeys.list();console.log("Authenticated:", keys.length, "key(s) found");Use the SDK to create a payment. You'll get back a payment object with a checkout URL that your customers would visit to pay.
import { Payvra } from "payvra";const payvra = new Payvra(process.env.PAYVRA_TEST_KEY!);const payment = await payvra.payments.create({ amount: "49.99", currency: "USDC", chain: "solana", metadata: { orderId: "order_123" },});console.log("Payment ID:", payment.id);console.log("Status:", payment.status);console.log("Checkout URL:", payment.checkoutUrl);When a payment completes, Payvra sends a webhook to your server. Set up a handler that verifies the signature and processes the event.
import express from "express";import crypto from "crypto";const app = express();app.use(express.raw({ type: "application/json" }));const WEBHOOK_SECRET = process.env.PAYVRA_WEBHOOK_SECRET!;app.post("/webhooks/payvra", (req, res) => { const payload = req.body.toString(); const webhookId = req.headers["webhook-id"] as string; const timestamp = req.headers["webhook-timestamp"] as string; const signature = req.headers["webhook-signature"] as string; // Reject stale events (> 5 min) const age = Math.abs(Date.now() / 1000 - Number(timestamp)); if (age > 300) return res.status(400).send("Timestamp too old"); // Verify signature const signed = `${webhookId}.${timestamp}.${payload}`; const expected = crypto .createHmac("sha256", WEBHOOK_SECRET) .update(signed) .digest("base64"); const received = signature.replace("v1,", ""); if (!crypto.timingSafeEqual( Buffer.from(expected, "base64"), Buffer.from(received, "base64"), )) { return res.status(400).send("Invalid signature"); } const event = JSON.parse(payload); console.log("Event:", event.type, event.data.id); // Handle the event if (event.type === "payment.completed") { // Fulfill the order console.log("Payment completed:", event.data.id); } res.json({ received: true });});app.listen(4242, () => console.log("Webhook server on :4242"));After your webhook handler processes the event, retrieve the payment to confirm its status. This is the belt-and-suspenders check, never rely on webhooks alone for fulfillment.
import { Payvra } from "payvra";const payvra = new Payvra(process.env.PAYVRA_TEST_KEY!);// Use the payment ID from step 3const payment = await payvra.payments.retrieve("pay_...");console.log("Payment ID:", payment.id);console.log("Status:", payment.status); // "completed"console.log("Amount:", payment.amount); // "49.99"console.log("Currency:", payment.currency); // "USDC"console.log("Chain:", payment.chain); // "solana"console.log("Settled at:", payment.settledAt);console.log("Tx hash:", payment.txHash);You've built and tested the full flow. Now swap your test key for a live key and you're accepting real payments.
// Before (sandbox):const payvra = new Payvra("sk_test_abc123...");// After (production):const payvra = new Payvra(process.env.PAYVRA_LIVE_KEY!);// That's it. Same code, real payments.// Checklist before going live:// 1. Replace sk_test_ with sk_live_ (use env vars!)// 2. Set your production webhook URL in the dashboard// 3. Verify your webhook endpoint returns 200// 4. Set your settlement currency and payout address// 5. Test one small live payment to confirm the flow