VVT-Pay
Provider Login

VVT-Pay API Documentation

Integrate programmable payment orchestration for regulated institutional workflows, enabling secure multi-rail settlement across traditional and blockchain-based payment networks.

Base URL

https://pay.virovita.io

Overview

The VVT-Pay API provides programmable payment and settlement infrastructure for regulated institutional workflows.

It enables authorized platforms to create and manage payment intents, track settlement status, and orchestrate compliant value flows through a secure REST interface.

Designed for regulated environments, starting in healthcare.

All requests require API key authentication via the x-api-key header, and responses follow standard HTTP status codes.

Features

  • RESTful API design following OpenAPI 3.0 standards
  • API Key authentication for machine-to-machine integration
  • Familiar payment rails: stablecoins (USDC, USDT, XRP) are preferred but not the only method. Providers can receive payments in USD (settled via USDC on XRPL) and EUR (via SEPA/IBAN). Additional rails may be added over time.
  • Real-time payment intent status tracking
  • HIPAA-compliant architecture with zero PHI retention
  • Rate limiting and security best practices
  • 24/7 server-to-server access with API key; no browser or user session required
  • Optional webhook URL (dashboard settings) for payment.completed notifications
  • Invoice API for platform fee billing and settlement reconciliation

Quick Start

Get started in three simple steps:

  1. Copy your API Key from the provider dashboard
  2. Store it in your .env file
  3. Include it in the x-api-key header for all requests

Content Type

All API requests must include the following header:

Content-Type: application/json

Authentication

VVT-Pay uses API Key authentication for all API integration. Dashboard login (email/password and OTP) is for human access to the provider dashboard only; for server-to-server calls you must use your API Key. Copy it from the dashboard and send it in every API request.

Get Your API Key

Log into your provider dashboard, open Settings or the Integration tab, and go to the API Key section. Click the eye icon to reveal your API Key (password confirmation required), then copy it to your clipboard.

Important: Your API Key is like your server's secret password. Store it securely in your .env file and never expose it in client-side code or version control systems.

Using Your API Key

Include your API Key in the x-api-key header for all authenticated requests:

x-api-key: vvt_your_api_key_here...

Machine-to-Machine Integration

For automated server-to-server communication, your API Key is the only credential you need. No OAuth, no token refresh, no login flows. Simply include it in every request header.

Example: Create Charge (Recommended for M2M)

curl -X POST https://pay.virovita.io/api/charge \
  -H "Content-Type: application/json" \
  -H "x-api-key: vvt_your_api_key_here" \
  -d '{
    "amount": "150.00",
    "currency": "USDC",
    "externalRef": "ORDER-123",
    "deliveryMethod": "both"
  }'

This returns both a checkout_url (for web) and qr_raw_data (for QR codes), perfect for automated payment processing.

Example: Create Payment Intent (Legacy)

curl -X POST https://pay.virovita.io/api/intents \
  -H "Content-Type: application/json" \
  -H "x-api-key: vvt_your_api_key_here" \
  -d '{
    "amount": "150.00",
    "currency": "USDC"
  }'

Key Benefits:

  • No expiration: Your API Key never expires (until you regenerate it)
  • 24/7 access: Works continuously with no browser or user session required
  • Simple integration: Just one header in every request
  • Secure by default: Use HTTPS and store keys in environment variables

Security Best Practices: Never hardcode your API Key in source code. Always use environment variables (e.g., process.env.VVT_API_KEY) and ensure your .env file is in .gitignore.

Payment Intent Endpoints

Create Payment Intent

POST /api/intents

Creates a new payment intent for settlement processing. The provider is automatically identified from the API Key.

Request Body

{
  "amount": "150.00",
  "currency": "USDC"
}

Parameters

FieldTypeRequiredDescription
amountstringYesDecimal amount (max 1,000,000)
currencyenumNoUSDC, USDT, or XRP (default: USDC)

Success Response (201)

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "providerRefId": "provider-uuid",
    "amount": 150.00,
    "currency": "USDC",
    "status": "PENDING",
    "ledgerTxHash": null,
    "createdAt": "2026-01-16T10:00:00.000Z",
    "updatedAt": "2026-01-16T10:00:00.000Z"
  }
}

Get Payment Intent by ID

GET /api/intents/:id

Returns a single payment intent by UUID. Use x-api-key header.

List Payment Intents

GET /api/intents

Retrieves all payment intents for the authenticated provider. Results are sorted by creation date in descending order.

Success Response (200)

{
  "success": true,
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "providerRefId": "provider-uuid",
      "amount": 150.00,
      "currency": "USDC",
      "status": "CONFIRMED",
      "ledgerTxHash": "0xabc123...",
      "createdAt": "2026-01-16T10:00:00.000Z",
      "updatedAt": "2026-01-16T10:05:00.000Z"
    }
  ]
}

Payment Intent Status

Payment intents progress through the following statuses:

  • PENDING - Initial state, awaiting settlement
  • CONFIRMED - Settlement confirmed on XRPL
  • FAILED - Settlement failed
  • CANCELLED - Payment intent cancelled

Charge Endpoints

Universal Settlement Gateway: Create hosted checkout pages with QR codes for both crypto (XRPL) and fiat (EUR/SEPA) payments.

Create Charge

POST /api/charge

Creates a charge with a hosted checkout page URL and QR code. Supports USDC, USDT, XRP (crypto) and EUR (fiat via SEPA). This is the recommended endpoint for machine-to-machine integration as it provides both payment methods in one response.

Machine-to-Machine Authentication

For automated server-to-server integration, use your API Key in the x-api-key header. This is the preferred method for production applications as it requires no login flow and works 24/7.

Alternative: JWT tokens via Authorization: Bearer header are available for dashboard access but not recommended for automated systems.

Headers (API Key)

x-api-key: vvt_your_api_key_here
Content-Type: application/json

Headers (JWT)

Authorization: Bearer <token>
Content-Type: application/json

Request Body

{
  "amount": "150.00",
  "currency": "USDC",
  "externalRef": "INV-001",
  "deliveryMethod": "both"
}

Parameters

FieldTypeRequiredDescription
amountstringYesDecimal amount
currencyenumNoUSDC, USDT, XRP, USD, EUR (default: USDC)
externalRefstringNoYour internal reference ID
deliveryMethodenumNo"both" (default): Returns both checkout_url and qr_raw_data
"link": Only checkout_url (for web/mobile apps)
"qr_code": Only qr_raw_data (for in-person/print)
patientEmailstringNoPatient email for notifications

Success Response (201)

{
  "success": true,
  "data": {
    "payment_id": "550e8400-e29b-41d4-a716-446655440000",
    "checkout_url": "https://pay.virovita.io/checkout/550e8400...",
    "qr_raw_data": "xrpl:r...?dt=123456&amount=150&currency=USDC",
    "instructions": "Scan with Xaman or Ledger. Funds settle in 3 seconds.",
    "delivery_method": "both"
  }
}

Using the Response:

  • checkout_url: Direct your customers to this URL for a hosted payment page. Works for both crypto and fiat payments.
  • qr_raw_data: Generate a QR code from this data string. For crypto: XRPL URI format (scan with Xaman/Ledger). For fiat: SEPA QR code format.
  • instructions: Display these payment instructions to your customers alongside the QR code or checkout link.

Note: Transactions are automatically processed when payment is detected on XRPL ledger or via SEPA bank transfer. You can configure webhooks to receive payment notifications.

Get Charge Details

GET /api/charge/:id

Retrieves charge details by payment ID (UUID) or external reference ID. Returns QR code data, checkout URL, and payment instructions. Use this endpoint to retrieve charge information anytime after creation.

Authentication

Use your API Key in the x-api-key header for machine-to-machine access:

x-api-key: vvt_your_api_key_here

URL Parameters

  • :id - Payment ID (UUID) or external reference ID used during charge creation
  • If UUID format detected, searches by payment_id
  • If non-UUID, searches by external_reference_id

Success Response (200)

{
  "success": true,
  "data": {
    "payment_id": "550e8400-e29b-41d4-a716-446655440000",
    "checkout_url": "https://pay.virovita.io/checkout/550e8400...",
    "qr_raw_data": "xrpl:r...?dt=123456&amount=150&currency=USDC",
    "instructions": "Scan with Xaman or Ledger. Funds settle in 3 seconds.",
    "amount": "150.00",
    "currency": "USDC"
  }
}

Response Fields:

  • payment_id: Unique identifier for this charge (store this for tracking)
  • checkout_url: Hosted payment page URL (for web/mobile redirects)
  • qr_raw_data: QR code data string (for crypto: XRPL URI format, for fiat: SEPA QR format)
  • instructions: Human-readable payment instructions to display to customer
  • amount: Payment amount as string
  • currency: Payment currency (USDC, USDT, XRP, USD, EUR)

Error Response (404)

{
  "success": false,
  "error": "Charge not found"
}

Returns 404 if the payment ID or external reference doesn't exist or belongs to another provider.

Implementation Guide

This guide walks you through integrating VVT-Pay into your healthcare provider application. Follow these steps to enable instant stablecoin settlement for your payment processing.

Quick Start

Get up and running in 5 minutes with this minimal integration:

  1. Copy your API Key from the provider dashboard (Settings or Integration tab)
  2. Store it in your backend .env file
  3. Create a charge when a patient initiates payment (POST /api/charge)
  4. Redirect to checkout_url or show QR from qr_raw_data; poll GET /api/charge/:id or use webhooks for status
  5. Fulfill service when payment is confirmed
# Create Charge (recommended) - returns checkout_url and qr_raw_data
curl -X POST https://pay.virovita.io/api/charge \
  -H "Content-Type: application/json" \
  -H "x-api-key: vvt_your_api_key_here" \
  -d '{"amount":"150.00","currency":"USDC","deliveryMethod":"both"}'

Note: No login required! Your API Key is your permanent credential. Copy it once from the dashboard and use it in all requests.

API Environments

VVT-Pay supports multiple environments. Configure via NEXT_PUBLIC_API_URL environment variable:

Current Environment: Custom

Current Base URL: https://pay.virovita.io

Example Configuration:

# Production
NEXT_PUBLIC_API_URL=https://api.pay.virovita.io

The application reads NEXT_PUBLIC_API_URL from your environment. No code changes needed when switching environments.

How to configure:

  1. Create or edit .env.local in your frontend root
  2. Add: NEXT_PUBLIC_API_URL=your-api-url
  3. Restart your Next.js dev server

Note: Always use HTTPS in production. The API uses TLS 1.2+ encryption for all requests. Development environment (localhost) is for testing only and should never be used for production data.

Prerequisites

Before you begin integration, ensure you have:

  • A registered VVT-Pay provider account with valid credentials
  • API access enabled (contact support if not activated)
  • HTTPS-enabled backend server (required for production)
  • Ability to make HTTP POST and GET requests to external APIs
  • Database storage for payment intent IDs and transaction references

Step 1: Get Your API Key

Log into your provider dashboard and copy your API Key. This is your permanent credential for all API requests—you won't need to log in again for API access.

What to Expect:

  • API Key format: vvt_ followed by 64 hexadecimal characters
  • Key never expires: Use it continuously until you regenerate it
  • Store securely: Copy it to your .env file immediately
  • One key per provider: Each provider account has a unique API Key

Important: Your API Key is visible in the dashboard only after confirming your password for security. Once copied, store it in your backend environment variables—never in frontend code.

Step 2: Configure Your Backend

Add your API Key to your backend environment configuration. This allows your server to authenticate with VVT-Pay without manual intervention.

Example Configuration:

# .env file
VVT_API_KEY=vvt_your_api_key_here
NEXT_PUBLIC_API_URL=https://api.pay.virovita.io

Security: Ensure your .env file is listed in.gitignore and never commit API Keys to version control.

Step 3: Create Charge (Recommended for M2M)

When a patient initiates a payment, use the Create Charge endpoint. This is the recommended approach for machine-to-machine integration as it provides both a checkout URL and QR code in one response. Include your API Key in the x-api-key header.

Why Use Charge Endpoint?

  • Returns both checkout_url (for web/mobile redirects) and qr_raw_data (for QR code generation)
  • Supports all payment methods: USDC, USDT, XRP (crypto) and EUR (fiat via SEPA)
  • Perfect for automated systems: One API call gives you everything needed
  • Flexible delivery: Choose "link", "qr_code", or "both" based on your use case

What to Expect:

  • Response time: 150-400ms under normal load
  • You receive: payment_id, checkout_url, qr_raw_data, instructions, amount, currency
  • checkout_url: Hosted payment page URL (redirect customers here for web/mobile)
  • qr_raw_data: QR code data string (generate QR code for in-person/print scenarios)
  • Store the payment_id: Use it to retrieve charge status later via GET /api/charge/:id

Important: The payment_id is your primary reference for tracking payments. Save it in your database along with the checkout_url and qr_raw_data. You can retrieve charge details anytime using GET /api/charge/:id with your API Key.

Step 4: Present Payment Options to Customer

After creating the charge, you have two options to present to your customer:

Option 1: Checkout URL (Web/Mobile Apps)

Use the checkout_url from the response. Redirect your customer to this URL for a hosted payment page that handles both crypto and fiat payments.

  • Best for: Web applications, mobile apps, email payment links
  • Customer experience: Professional hosted page with payment options
  • Implementation: Simple redirect or link in your UI

Option 2: QR Code (In-Person/Print)

Use the qr_raw_data from the response. Generate a QR code from this data string and display it to your customer.

  • Best for: Point-of-sale, printed invoices, in-person transactions
  • Customer experience: Scan with wallet app (Xaman, Ledger) or banking app (for SEPA)
  • Implementation: Use any QR code library to generate image from qr_raw_data string
  • For crypto: QR contains XRPL URI (xrpl:...) - scan with XRPL wallet
  • For fiat: QR contains SEPA QR format - scan with banking app

Tip: Use deliveryMethod: "both" to get both options in one response. This gives you maximum flexibility to choose the best method for each transaction.

Display the payment instructions from the response alongside your chosen delivery method. The patient will send payment directly from their wallet (crypto) or bank account (fiat) to the settlement address on the XRP Ledger.

What to Expect:

  • Payment remains in PENDING status until settlement
  • Settlement typically occurs within 3-5 minutes of patient sending funds
  • No webhook required: Use polling or real-time status checks to detect confirmation

Step 5: Poll for Payment Status

Periodically check status with your API Key: use GET /api/charge/:id for charges (payment_id) or GET /api/intents/:id for payment intents. When status is CONFIRMED, settlement is complete and funds are available.

Recommended Polling Strategy:

  • Initial checks: Every 10 seconds for the first minute
  • Subsequent checks: Every 30 seconds for up to 10 minutes
  • After 10 minutes: Check every 2 minutes until confirmed or timeout
  • Timeout: Consider failed after 30 minutes without confirmation

What to Expect:

  • Status progression: PENDINGCONFIRMED
  • Confirmed responses include: ledgerTxHash (blockchain transaction ID)
  • Failed payments: Status changes to FAILED with error details
  • Always use your API Key: Include x-api-key header in all requests

Step 6: Handle Confirmation

Once the payment intent status is CONFIRMED, update your internal records and fulfill the service. The transaction is now immutable on the XRP Ledger.

What to Expect:

  • ledgerTxHash: Save this for audit trail and reconciliation
  • updatedAt: Timestamp of settlement confirmation
  • VVT rewards: Automatically recorded to your internal ledger (not on-chain)
  • No additional API calls needed: Settlement is complete

Webhooks (Optional)

Set your webhook URL in the provider dashboard (Settings). When a payment completes, we POST to your URL withevent: payment.completed and a JSON payload (paymentIntentId, transactionHash, amount, currency, recipientWallet, settledAt, timestamp). Verify theX-VVT-Signature header (HMAC SHA-256 of the raw body) to ensure authenticity.

Alternative: use polling (GET /api/charge/:id or GET /api/intents/:id) if you prefer not to expose an endpoint.

Integration Checklist

  • Created charge (or payment intent) before displaying payment UI
  • Stored payment_id or intent ID in database for tracking
  • Implemented polling mechanism for status checks
  • Handled CONFIRMED status and updated internal records
  • Saved ledgerTxHash for audit trail
  • Tested error scenarios (network failures, invalid amounts, etc.)
  • Implemented rate limiting to respect API limits

Expected Response Times

EndpointTypical Response TimeMaximum Expected
POST /api/intents150-400ms1s
GET /api/intents100-300ms500ms
POST /api/charge150-400ms1s
GET /api/charge/:id100-300ms500ms

API Versioning

VVT-Pay API currently uses version 1.0. All endpoints are stable and backward-compatible. Future versions will be announced with a 6-month deprecation notice.

Current Version: v1.0
Version Format: Semantic versioning (MAJOR.MINOR.PATCH)
Backward Compatibility: Minor and patch versions are backward-compatible

Idempotency

Payment intent creation is idempotent. If you receive a network error but are uncertain whether the request was processed, you can safely retry with the same parameters. The API will return the same payment intent if it was already created.

Best Practice: Store payment intent IDs immediately after creation. If a network error occurs, check for an existing intent with the same parameters before retrying to avoid duplicate records.

Error Handling Best Practices

Implement robust error handling to ensure reliable payment processing:

  • Network failures: Implement retry logic with exponential backoff
  • 401 Unauthorized: Invalid API Key - Verify your key in the dashboard
  • 400 Validation errors: Validate input before sending to API
  • 429 Rate limit: Wait for reset window or implement request queuing
  • 500 Server errors: Log for monitoring and retry after delay

Testing Your Integration

Before deploying to production, thoroughly test your integration:

  1. Test API key authentication with valid and invalid keys
  2. Create payment intents with various amounts and currencies
  3. Simulate polling scenarios and verify status updates
  4. Test error handling (invalid amounts, network timeouts, etc.)
  5. Verify ledgerTxHash is stored correctly for confirmed payments
  6. Test rate limiting behavior to ensure compliance

Other APIs (same x-api-key): Profile (webhook URL, branding), Invoices (create, list, PDF). See dashboard for usage.

Need Help? For implementation support or questions, contact our integration team at info@pay.virovita.io. We provide dedicated support during your integration phase.

Code Examples

Copy your API Key from the dashboard and use it in the x-api-key header for all API requests. No login or token management required.

# Set your API Key (from dashboard)
API_KEY="vvt_your_api_key_here"

# Create Payment Intent
curl -X POST https://pay.virovita.io/api/intents \
  -H "Content-Type: application/json" \
  -H "x-api-key: $API_KEY" \
  -d '{
    "amount": "150.00",
    "currency": "USDC"
  }'

# List Payment Intents
curl -X GET https://pay.virovita.io/api/intents \
  -H "x-api-key: $API_KEY"

# Create Charge (with QR code and checkout URL)
curl -X POST https://pay.virovita.io/api/charge \
  -H "Content-Type: application/json" \
  -H "x-api-key: $API_KEY" \
  -d '{
    "amount": "150.00",
    "currency": "USDC",
    "externalRef": "INV-001",
    "deliveryMethod": "both"
  }'

Note: In production, always load your API Key from environment variables. Never hardcode it in your source code or commit it to version control.

Error Handling

The VVT-Pay API uses standard HTTP status codes to indicate success or failure. All error responses follow a consistent format.

Error Response Format

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message"
  }
}

HTTP Status Codes

CodeDescription
200Success
201Created
400Bad Request (validation error)
401Unauthorized (missing or invalid API key)
403Forbidden (Account deactivated or insufficient permissions)
404Not Found
429Too Many Requests (rate limit exceeded)
500Internal Server Error

Example Error Response

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "amount: Amount must be a valid decimal"
  }
}

Rate Limits

To ensure system stability and prevent abuse, VVT-Pay API enforces rate limits on all endpoints.

Rate Limit Policy

  • Window: 15 minutes (900 seconds)
  • Maximum Requests: 100 requests per window per IP address
  • Headers: Rate limit information is included in response headers

Note: When rate limit is exceeded, you will receive a 429 Too Many Requests response. Wait for the window to reset before making additional requests.

Rate Limit Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705320000