Vulta provides a REST API, JavaScript widget, and iframe embed for adding crypto and card payment acceptance to any website. API keys and webhooks are available on the Business plan. No merchant account or KYC required to get started.

Developers

Build on Vulta.

Embed a full checkout in two lines. Receive signed webhooks when payments confirm. Manage everything via REST API. No custody, no KYC on your side.

Hosted payment links

Share a URL. Works on any device, no integration required. Available on all plans.

Embeddable checkout

Iframe or script tag. Drops a full checkout widget into any page. Max and Business plans.

HMAC-signed webhooks

HTTP POST on every payment event, signed with your secret. Business plan.

REST API + API keys

Programmatic access with long-lived API keys. Manage links, destinations, and more. Business plan.

Quick start

Server-created checkout in three steps

Use your Vulta API key only on your backend. Your app creates a hosted checkout URL, sends the customer there, and receives a signed webhook when the payment confirms.

01

Create a checkout session from your backend

Send the amount, currency, and your internal reference ID. Set use_all_payout_destinations to let Vulta snapshot every active wallet address on your account.

curl https://vulta.one/api/checkout/sessions \
  -H "Authorization: Bearer vlt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount_fiat": "29.00",
    "fiat_currency": "USD",
    "external_reference_id": "sub_123",
    "use_all_payout_destinations": true
  }'

{
  "id": "018f4f3e-2e8b-7a21-9f0c-0b6f56a7d3b1",
  "checkout_url": "https://vulta.one/pay/018f4f3e-2e8b-7a21-9f0c-0b6f56a7d3b1"
}
02

Redirect the customer to the provider-ready checkout

Open the returned checkout URL from a user click in your app. Vulta handles wallet selection, card provider routing, crypto payment instructions, and status polling.

// Browser code in your SaaS app
button.addEventListener('click', async () => {
  const response = await fetch('/api/billing/vulta-checkout', { method: 'POST' });
  const { checkout_url } = await response.json();
  window.location.assign(checkout_url);
});
03

Activate access from the signed webhook

Store your subscription or order ID in external_reference_id, verify the HMAC signature, then fulfill the purchase when event_type is payment.confirmed.

API reference

REST API

Merchant API endpoints require a user JWT or API key. Payer-facing checkout URLs stay public so customers can complete a payment, but they are not a way to create arbitrary merchant checkouts.

Authentication

# Recommended for server-to-server integrations
Authorization: Bearer vlt_live_a1b2c3d4e5f6...

# Also accepted for dashboard-style clients
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Checkout creation

POST/api/checkout/sessionsCreate a hosted checkout URLMax
POST/api/payment-requestsCreate a one-off payment requestMax
GET/api/payment-requestsList payment requests (transactions)

Headless checkout — no Vulta UI

Build your own card and crypto buttons. Pass the amount and receive a direct provider URL or crypto address — the Vulta domain never appears to your users. Works in Telegram bots, mobile apps, and any custom UI.

POST/api/checkout/cryptoGet a crypto address for any network / assetBusiness
POST/api/checkout/cardGet a direct card-provider URL (MoonPay, Transak…)Business
# Crypto — returns the exact address to show your user
curl https://vulta.one/api/checkout/crypto \
  -H "Authorization: Bearer vlt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "network": "TRON",
    "asset": "USDT",
    "amount_fiat": "150.00",
    "external_reference_id": "order_456"
  }'

{
  "payment_request_id": "uuid",
  "address": "TJRyWwFs9wTFGZg3JbrVriFbNfCug5tDeC",
  "network": "TRON",
  "asset": "USDT",
  "amount_fiat": "150.00"
}

# Card — returns a direct provider URL, open it for your user
curl https://vulta.one/api/checkout/card \
  -H "Authorization: Bearer vlt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount_fiat": "75.00",
    "external_reference_id": "order_789"
  }'

{
  "payment_request_id": "uuid",
  "provider_url": "https://buy.moonpay.com/...",
  "provider": "moonpay"
}

Your webhook fires with payment.confirmed when payment arrives. Use external_reference_id to match the event to your order.

Account configuration

GET/api/payment-linksList your payment links
POST/api/payment-linksCreate a payment link
PATCH/api/payment-links/{id}Update a payment link
DELETE/api/payment-links/{id}Deactivate a payment link
GET/api/payout-destinationsList payout destinations (wallets)
POST/api/payout-destinationsAdd a payout destination
curl https://vulta.one/api/payment-requests \
  -H "Authorization: Bearer vlt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "one_off": {
      "pricing_mode": "fixed_fiat",
      "amount_fiat": "250.00",
      "fiat_currency": "USD",
      "external_reference_id": "invoice_1042",
      "use_all_payout_destinations": true
    }
  }'

API keys and webhooks

GET/api/apikeysList API keysBusiness
POST/api/apikeysGenerate a new API keyBusiness
DELETE/api/apikeys/{id}Revoke an API keyBusiness
GET/api/settings/webhookGet webhook settingsBusiness
PUT/api/settings/webhookUpdate webhook URL + secretBusiness

Webhooks

Real-time payment events

Available on the Business plan. Configure your endpoint in Settings → Webhooks.

Vulta delivers HMAC-SHA256-signed POST requests to your endpoint on every payment event. Verify the X-Vulta-Signature header to confirm authenticity.

Webhook payload

// POST https://your-site.com/vulta-webhook
// Headers:
//   Content-Type: application/json
//   X-Vulta-Signature: <hmac-sha256-hex>

{
  "event_type": "payment.confirmed",
  "payment_request_id": "a1b2c3d4-e5f6-...",
  "external_reference_id": "sub_123",
  "amount_fiat": "29.00",
  "fiat_currency": "USD",
  "status": "CONFIRMED",
  "merchant_id": "c3d4e5f6-..."
}

Events

payment.detectedTransaction found on-chain. Not yet confirmed (0 confirmations).
payment.confirmedPayment confirmed (6+ block depth). Safe to fulfill.

Signature verification — Node.js

const crypto = require('crypto');

function verifyVultaWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)  // raw bytes, not JSON.stringify
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express example
app.post('/vulta-webhook', express.raw({ type: '*/*' }), (req, res) => {
  const sig = req.headers['x-vulta-signature'];
  if (!verifyVultaWebhook(req.body, sig, process.env.VULTA_WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  const event = JSON.parse(req.body);
  if (event.event_type === 'payment.confirmed') {
    // fulfill order, unlock subscription using external_reference_id
  }
  res.json({ ok: true });
});

Signature verification — Python

import hmac, hashlib

def verify_vulta_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        raw_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)