Build on Chainvara in an afternoon
One REST API for wallets, transfers, payouts, tokens and compliance. Every call goes through the same policies, approvals and screening as the console, and every change reaches you as a signed webhook.
$ curl -X POST /api/v1/transfers …
201 transfer_8f2… pending_approval
webhook transfer.approved FOS-Signature ✓
webhook transfer.submitted 0x7a1…e04
webhook transfer.confirmed 12 confirmations
→ order #1042 marked paid
Quick start
Create a key
Sign up, open Developers and create a test key (fos_test_…). Test keys run on public test networks; live keys (fos_live_…) on mainnets.
Call the API
Send the key as a Bearer token. Add an Idempotency-Key to every POST so a retry never pays twice.
Listen
Register an https endpoint for webhooks, verify each signature, and react to transfer.confirmed.
curl https://www.chainvara.com/api/v1/transfers \
-H "Authorization: Bearer $CHAINVARA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{ "wallet_id": "…", "asset": "USDC", "amount": "250", "destination": "0x…" }'REST API
Base URL
https://www.chainvara.com/api/v1, JSON in and out.
Scoped keys
Each key has scopes (wallets:read, transfers:write…), an environment and an optional expiry. Revoke anytime.
Idempotency
An Idempotency-Key on POST replays the original answer; a different body with the same key is refused.
Rate limits
Per key and per minute according to your plan, with X-RateLimit headers and Retry-After on 429.
Wallets
Transfers and operations
Data and compliance
Errors use one shape: { "error": { "type", "code", "message", "request_id" } }. Every field is in the OpenAPI specification.
TypeScript SDK
One dependency-free ES module for Node.js 18+ with full types, automatic retries on network errors and 5xx, idempotency keys and webhook verification.
import { Chainvara } from "./chainvara.js";
const cv = new Chainvara(process.env.CHAINVARA_API_KEY);
// A deposit wallet for a customer.
const wallet = await cv.wallets.create({
network: "solana", external_user_id: user.id,
});
const req = { wallet_id: treasury.id, asset: "USDC",
amount: "250", destination: "@partner" };
const preview = await cv.transfers.preview(req);
if (preview.decision.outcome !== "deny") {
await cv.transfers.create(req, { idempotencyKey: order.id });
}Signed webhooks
Every event is POSTed to your https endpoint with a FOS-Signature: t=…,v1=… header: an HMAC-SHA256 of the timestamp and the raw body with your endpoint secret. Deliveries are retried with backoff and never sent to private addresses.
import { verifyWebhook } from "./chainvara.js";
app.post("/webhooks/chainvara", express.text({ type: "*/*" }), async (req, res) => {
const event = await verifyWebhook(req.body, req.get("FOS-Signature"),
process.env.CHAINVARA_WEBHOOK_SECRET); // throws if forged or replayed
if (event.type === "transfer.confirmed") await markPaid(event.data.id);
res.sendStatus(200);
});Go further
Get your sandbox key
Free on public test networks, with the same API, policies and webhooks as production.