Enter at least two characters to search. Searching documentation… No matching sections. Try an endpoint, field or event name.

Libraries

View as Markdown

Use the official PHP or Laravel library, integrate directly over HTTPS from Node.js, Python or C#, or install the WooCommerce plugin. Every API request has examples in six languages.

On this page

Set up your language

Choose a language in any request example; the documentation remembers it as you browse. Each example includes its imports, authentication and response handling. PHP and Laravel use the official libraries; cURL, Node.js, Python and C# call the REST API directly.

Language Requirements Run an example
cURL cURL 7.76+ in Bash, including WSL or Git Bash on Windows. Paste a request into your terminal. In PowerShell, use the C# example or open a Bash shell for the cURL syntax.
PHP PHP 8.2+ and Composer, with a PSR-18 HTTP client. Install velirapay/velirapay-php and, if you need an HTTP client, guzzlehttp/guzzle. Save a request example as charge.php and run php charge.php.
Laravel Laravel 12 with PHP 8.2+, or Laravel 13 with PHP 8.3+, and velirapay/velirapay-laravel. Set the key in your application .env, then run the example in a controller or application service.
Node.js Node.js 22+; the examples use the built-in fetch API. Save the example as charge.mjs and run node charge.mjs. No npm package is required.
Python Python 3.11+ with the requests package. Install with python -m pip install requests, save charge.py, then run python charge.py.
C# .NET 8+; the examples use HttpClient and System.Text.Json. Run dotnet new console -n VeliraPayExample, replace Program.cs with the example, then run dotnet run --project VeliraPayExample. No NuGet package is required.

Configure your API key

Create a test key in Developers → API keys and set VELIRAPAY_API_KEY in the environment of the process running your code. For a local terminal session, replace the placeholder in one of these commands:

Bash

Copy failed. Select the code and copy it manually.

export VELIRAPAY_API_KEY='vp_test_replace_me'
PowerShell

Copy failed. Select the code and copy it manually.

$env:VELIRAPAY_API_KEY = 'vp_test_replace_me'

Laravel loads the value from .env. The standalone PHP, Node.js, Python and C# examples read the process environment; creating a .env file alone does not load it. Keep keys in server configuration, outside source control and browser code. Use a vp_live_ key only when you intend to create live objects.

Create, check and simulate your first charge

Webhook receivers have their own six-language examples, including signature checks, the verification challenge and a signed cURL request for local testing. Build a webhook receiver

Official packages

The PHP and Laravel libraries wrap the REST API, use the MIT license and install with Composer. This page describes version 0.6 of both, and version 0.3 of the GPL-licensed WooCommerce plugin.

PHP velirapay/velirapay-php

Every endpoint of the API, typed objects, automatic retries and webhook verification, for any PHP application.

PHP 8.2 or later, with any PSR-18 HTTP client

Laravel velirapay/velirapay-laravel

The PHP library set up from your .env, a facade, and webhooks dispatched as Laravel events.

Laravel 12 with PHP 8.2+, or Laravel 13 with PHP 8.3+

WooCommerce velirapay/velirapay-woocommerce

A payment method for the classic and the block checkout: each order becomes an invoice the customer pays on a hosted page, in the coin of their choice.

PHP 8.1 or later, with WordPress 6.4 or later and WooCommerce 8.3 or later

PHP

Install it with Composer. It sends requests through the PSR-18 HTTP client your project already has; with none, add Guzzle as well.

Terminal

Copy failed. Select the code and copy it manually.

composer require velirapay/velirapay-php
Terminal

Copy failed. Select the code and copy it manually.

composer require guzzlehttp/guzzle

Create a client with your API key, charge the customer with what you already know about them, and send them to the charge's checkout page:

PHP

Copy failed. Select the code and copy it manually.

<?php

use VeliraPay\VeliraPayClient;

require __DIR__.'/vendor/autoload.php';

$apiKey = getenv('VELIRAPAY_API_KEY') ?: throw new RuntimeException('Set VELIRAPAY_API_KEY.');
$velirapay = new VeliraPayClient($apiKey);

$charge = $velirapay->charges->create([
    'amount' => '49.90',
    'currency' => 'EUR',
    'asset' => 'BTC',
    'description' => 'Order #1042',
    'customer' => [
        'email' => 'ada@example.com',
        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
    ],
    'metadata' => ['order_id' => '1042'],
    'success_url' => 'https://example.com/orders/1042',
], 'order-1042-attempt-1');

header('Location: '.$charge->checkoutUrl, true, 303);
exit;

Run this redirect in a web request before sending any output. Save the charge ID with your order, and reuse the same idempotency key when retrying this payment attempt.

To see which coins to offer, and what a charge in each must at least come to:

PHP

Copy failed. Select the code and copy it manually.

foreach ($velirapay->assets->list(['currency' => 'EUR']) as $asset) {
    if ($asset->accepted) {
        echo "{$asset->name} on {$asset->network}, from {$asset->minimumPrice} {$asset->currency}\n";
    }
}

When the webhook arrives, one call checks its signature and reads it:

PHP

Copy failed. Select the code and copy it manually.

<?php

use VeliraPay\Exceptions\SignatureVerificationException;
use VeliraPay\Webhooks\Webhook;

require __DIR__.'/vendor/autoload.php';

$secret = getenv('VELIRAPAY_WEBHOOK_SECRET') ?: throw new RuntimeException('Set VELIRAPAY_WEBHOOK_SECRET.');

try {
    $event = Webhook::constructEvent(
        file_get_contents('php://input'),
        $_SERVER['HTTP_X_VELIRAPAY_SIGNATURE'] ?? null,
        $secret,
    );
} catch (SignatureVerificationException) {
    http_response_code(400);
    exit;
}

if ($event->isVerification()) {
    header('Content-Type: application/json');
    echo $event->challengeResponse();
    exit;
}

if ($event->test || $event->mode !== 'live') {
    http_response_code(204);
    exit;
}

if ($event->is('charge.payment_detected', 'charge.late_payment')) {
    $txid = $event->transaction->txid; // the transfer that was seen
}

if ($event->is('charge.paid')) {
    $orderId = $event->charge->metadata['order_id'];
}

http_response_code(204);

A missing, wrong or expired signature throws a SignatureVerificationException: answer with a 400 and stop there. A delivery that does not get a 2xx is retried, so a genuine one still gets through once your check is fixed.

Set VELIRAPAY_WEBHOOK_SECRET to the endpoint's signing secret. Answer the verification challenge before handling payments, then press Verify on the endpoint. This example handles live payments only; keep test-mode orders separate and never fulfil an order for a dashboard sample. Before returning 204, persist the event and update the matching order safely. Store eventId, falling back to id, to avoid handling the same event twice.

Laravel

The Laravel package sets up the PHP library for you and receives webhooks on a route of its own.

Terminal

Copy failed. Select the code and copy it manually.

composer require velirapay/velirapay-laravel

Add your API key and your webhook endpoint's signing secret to .env:

.env

Copy failed. Select the code and copy it manually.

VELIRAPAY_API_KEY=vp_test_replace_me
VELIRAPAY_WEBHOOK_SECRET=whsec_…

Call the API through the facade:

PHP

Copy failed. Select the code and copy it manually.

use VeliraPay\Laravel\Facades\VeliraPay;

$charge = VeliraPay::charges()->create([
    'amount' => '49.90',
    'currency' => 'EUR',
    'asset' => 'BTC',
    'customer' => ['ip_address' => $request->ip(), 'user_agent' => $request->userAgent()],
    'metadata' => ['order_id' => '1042'],
], 'order-1042-attempt-1');

return redirect()->away($charge->checkoutUrl);

Then add https://your-app.example/velirapay/webhook as a webhook endpoint. Each delivery is checked and dispatched as a Laravel event, such as ChargePaid, for your listeners to handle; ChargePaymentDetected and ChargeLatePayment also carry the transfer that was seen as $event->transaction. A delivery whose signature is missing, wrong or too old is answered with 403 and dispatches nothing.

PHP

Copy failed. Select the code and copy it manually.

use VeliraPay\Laravel\Events\ChargePaid;

class FulfilOrder
{
    /**
     * Handle a confirmed live payment.
     */
    public function handle(ChargePaid $event): void
    {
        if ($event->webhook->test || $event->webhook->mode !== 'live') {
            return;
        }

        $orderId = $event->charge->metadata['order_id'];
    }
}

Add your order lookup and fulfilment inside the listener: check the expected charge, amount and currency, and persist the event ID with the order update to handle duplicates. This listener deliberately handles live orders; use a separate test-order path to exercise it with a test key.

On Laravel 13, a webhook route you register yourself must stay clear of CSRF protection: define it in routes/api.php, or exclude its path with $middleware->preventRequestForgery(except: [...]) in bootstrap/app.php (validateCsrfTokens on Laravel 12).

It also comes with helpers to fake API calls and send signed webhooks in your tests.

WooCommerce

Download the zip from the plugin's releases and upload it under Plugins → Add New → Upload Plugin. Then, under WooCommerce → Settings → Payments → VeliraPay, paste an API key and the signing secret of a webhook endpoint pointing at the URL the page shows, and press Verify on the endpoint's page in the dashboard. The plugin only creates, reads and voids invoices, so a key restricted to invoices:read and invoices:write is all it needs.

Because the store does not know which coin a customer wants, each order becomes an invoice, whose hosted page lets them pick one. The order moves to Processing or Completed once the payment confirms, a missed webhook is caught by polling, and a note on the order says when your share went out and when it reached your wallet. See the releases

What they handle

  • Authentication with your API key, whose prefix tells them whether you are in live or test mode.
  • Typed objects for your account (support phone and business details included), the coins on offer and their minimums, charges, invoices, payment links, coupons, payouts, events and webhook endpoints, keeping every field the API sends, and an Asset enum for the coins.
  • The customer's details on every charge, the transfer a charge.payment_detected or charge.late_payment webhook is about, and the payout a payout.sent or payout.confirmed webhook is about.
  • An iterator that walks a whole list, fetching each page as it gets there.
  • Retries after network errors, rate limits and outages, and while an earlier attempt of the same write is still being worked on (409), with an idempotency key so a retried write is carried out once.
  • An exception for each kind of error, with validation messages keyed by field.
  • Webhook signature checks, including the five-minute limit on a signature's age.

Other languages

The Node.js, Python and C# examples use standard HTTP clients, not a VeliraPay SDK. They send the same Bearer token and JSON as cURL, check HTTP errors and set request timeouts. Reuse HttpClient in a long-running C# service. If you add retries, keep the same idempotency key and request body for each attempt.

Webhook verification is shown separately in PHP, Node.js, Python and C#, including raw request bytes, signature rotation and the five-minute timestamp check. Verify webhook signatures

Start with authentication