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.

Desarrolladores

Construye en Vulta.

Integra un checkout completo en dos líneas. Recibe webhooks firmados cuando los pagos se confirman. Gestiona todo vía REST API. Sin custodia, sin KYC de tu parte.

Enlaces de pago alojados

Comparte una URL. Funciona en cualquier dispositivo, sin integración requerida. Disponible en todos los planes.

Checkout integrado

Iframe o script tag. Añade un widget de checkout completo a cualquier página. Planes Pro y Business.

Webhooks firmados con HMAC

HTTP POST cuando se confirma un pago, firmado con tu secreto. Plan Business.

REST API + API keys

Acceso programático con API keys de larga duración. Gestiona enlaces, destinos y más. Plan Business.

Inicio rápido

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,
    "payer_email": "customer@example.com",
    "expires_at": "2026-06-10T12:00:00Z"
  }'

{
  "id": "018f4f3e-2e8b-7a21-9f0c-0b6f56a7d3b1",
  "checkout_url": "https://vulta.one/pay/018f4f3e-2e8b-7a21-9f0c-0b6f56a7d3b1",
  "payment_request": { "id": "...", "status": "OPEN", ... }
}
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.

Referencia API

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.

Autenticación

# 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-requestsCrear una solicitud de pago puntualMax
GET/api/payment-requestsListar solicitudes de pago (transacciones)

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. For bots and custom checkout UIs, use these headless endpoints instead of raw payment request creation.

GET/api/checkout/providersList available card providers with minimum amounts
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_crypto": "150.00",
    "external_reference_id": "order_456"
  }'

{
  "payment_request_id": "uuid",
  "payment_request_option_id": "uuid",
  "address": "TJRyWwFs9wTFGZg3JbrVriFbNfCug5tDeC",
  "network": "TRON",
  "asset": "USDT",
  "amount_fiat": null,
  "fiat_currency": null,
  "amount_crypto": "150.00",
  "encoded_amount": null,
  "amount_to_send": "150.00"
}

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

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

The crypto endpoint creates the request, selects the payment option, and returns the exact address to show the payer. Send either amount_crypto or amount_fiat with fiat_currency. Your webhook fires with payment.confirmed when payment arrives. Use external_reference_id to match the event to your order. If a wallet pool is enabled, amount_to_send usually equals the requested crypto amount; otherwise it may include a tiny encoded suffix for deterministic matching. If all matching pool addresses are busy for that amount, the endpoint returns 409 Conflict.

Account configuration

GET/api/payment-linksListar tus enlaces de pago
POST/api/payment-linksCrear un enlace de pago
PATCH/api/payment-links/{id}Actualizar un enlace de pago
DELETE/api/payment-links/{id}Desactivar un enlace de pago
GET/api/payout-destinationsListar destinos de pago (wallets)
POST/api/payout-destinationsAñadir un destino de pago
# One-off payment request
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
    }
  }'

# Payment link with pinned card providers (optional)
curl https://vulta.one/api/payment-links \
  -H "Authorization: Bearer vlt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Pro Plan",
    "pricing_mode": "fixed_fiat",
    "fixed_amount_fiat": "49.00",
    "fixed_amount_currency": "USD",
    "is_hybrid": true,
    "payout_destination_ids": ["uuid"],
    "preferred_providers": ["moonpay", "transak"]
  }'
Important: POST /api/payment-requests creates an OPEN request for a hosted/custom checkout flow. It does not select a crypto option by itself. A payer must open the checkout and select an option, or your integration must call POST /api/payment-requests/{id}/select-option. For Telegram bots and server-side crypto checkouts, prefer POST /api/checkout/crypto.

API keys and webhooks

GET/api/apikeysListar API keysBusiness
POST/api/apikeysGenerar nueva API keyBusiness
DELETE/api/apikeys/{id}Revocar una API keyBusiness
GET/api/settings/webhookObtener configuración de webhookBusiness
PUT/api/settings/webhookActualizar URL + secreto de webhookBusiness

API key endpoints accept vlt_live_... bearer keys. Webhook settings are configured from an authenticated dashboard session in Settings → Webhooks.

Webhooks

Eventos de pagos confirmados

Disponible en el plan Business. Configura tu endpoint en Ajustes → Webhooks.

Vulta entrega solicitudes POST firmadas con HMAC-SHA256a tu endpoint cuando se confirma un pago. Verifica el encabezado X-Vulta-Signature para confirmar la autenticidad.

Payload del webhook

// 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",
  "tx_hash": "0xabc123...",
  "status": "CONFIRMED",
  "merchant_id": "c3d4e5f6-..."
}

Eventos

payment.confirmedPago confirmado on-chain o por el proveedor de tarjeta. Seguro para cumplir el pedido.

Verificación de firma — 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 });
});

Verificación de firma — 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)