Welcome to Fundsvera API

Fundsvera provides a comprehensive suite of payment and virtual account payment collections & bank transafer API. Our infrastructure enables businesses to accept payments, create, manage, and monitor virtual accounts seamlessly.

Free API Integration Support! 🎉

We offer FREE integration assistance to help you get started quickly. Our team of experts is ready to help you integrate our APIs seamlessly.

Contact Our Integration Team

Core Features

  • Payment collections
  • Virtual account creation for customers
  • Real-time transaction monitoring
  • Webhook notifications for events
  • Secure authentication with API keys
  • Comprehensive transaction history
Base URL: https://fundsvera.co/api/v1

Authentication

All API requests require authentication using your API keys in the request headers.

API Credentials

After business onboarding, you will receive:

  • Public Key - Your business public identifier
  • Secret Key - Your private authentication key (keep secret!)

Required Headers

HeaderFormatRequiredDescription
Authorization Bearer {secret_key} Yes Your business secret key
Public-Key {public_key} Yes Your business public key
Content-Type application/json Yes Request body format

Virtual Account (Create)

Create a virtual bank account for a customer. If an account already exists, it will be returned instead of creating a duplicate.

POST
https://fundsvera.co/api/v1/create-virtual-account

Request Parameters

ParameterTypeRequiredValidationDescription
email string Yes Valid email format Customer's email address
name string Yes Alphanumeric, spaces, dashes Customer's name
bank_code string Yes Must be "100033" Bank code (currently Palmpay)
phone string Yes Exactly 11 digits Customer's phone number

Example Request

{
    "email": "[email protected]",
    "name": "Bolaji Olami",
    "bank_code": "100033",
    "phone": "08012345678"
}

Success Response (200 OK)

{
    "status": "SUCCESS",
    "message": "Virtual account number is now created and activated",
    "customer": {
        "customer_email": "[email protected]",
        "customer_phone": "08012345678",
        "customer_name": "Bolaji Olami"
    },
    "virtual_account": {
        "bank_name": "Palmpay",
        "account_name": "Fundsvera - Bol Fv",
        "account_number": "1234567890",
        "bank_code": "100033",
        "account_status": "Active"
    },
    "business": {
        "business_name": "Your Business Name",
        "business_email": "[email protected]"
    }
}

Initiate Bank Transfer (Secured Checkout)

Create a time‑limited virtual bank account and a secured checkout URL for a customer to complete a bank transfer payment. The account details are valid for 30 minutes.

POST
https://fundsvera.co/api/v1/secured-checkout

Request Parameters

ParameterTypeRequiredValidationDescription
customer_email string Yes Valid email address Customer's email
customer_name string Yes Alphanumeric, spaces, dashes, underscores Customer's full name
amount number Yes ≥ 100 (NGN) Amount to be paid
request_id string Yes Minimum 20 characters, unique per business Your unique transaction reference
redirect_url string Yes Must start with http or https, no query parameters Where we redirect your customer to after the payment
customer_phone string Optional Exactly 11 digits Customer's phone number

Example Request

{
    "customer_email": "[email protected]",
    "customer_name": "Bolaji Ola",
    "amount": 5000,
    "request_id": "unique-ref-1234567890abcdefghijk",
    "redirect_url": "https://your-website.com/success-page",
    "customer_phone": "08012345678"
}

Success Response (200 OK)

{
    "status": "Pending",
    "message": "Account details generated successfully",
    "customer_email": "[email protected]",
    "customer_name": "Bolaji Ola",
    "bank_name": "Bank Name",
    "account_name": "Fundsvera / Merchant Name",
    "account_number": "1234567890",
    "validity": "30 minutes",
    "request_id": "unique-ref-1234567890abcdefghijk",
    "trx_ref": "Tref...",
    "checkout_url": "https://fundsvera.co/secured-checkout/?ref=...&sig=...&D=...",
    "business_name": "Your Business Name",
    "business_email": "[email protected]"
}

The checkout_url is a unique, signed link that you can redirect your customer to. It displays payment instructions and an auto‑expiry timer.

Error Responses

HTTP StatusError Message
400Please input valid customer email
400Please input valid customer name
400Please input valid amount greater than or equal to 100
400Duplicate request ID, please use a unique request ID
401Unauthorized request please use valid keys
500System busy please try again later

Webhook Security

Fundsvera signs all webhook payloads with an HMAC‑SHA256 signature using your business secret key (the same key used for API authentication). The signature is sent in the X-FUNDSVERA-SIGNATURE header.

How to Verify

On your webhook endpoint, recalculate the HMAC‑SHA256 of the raw request body using your secret key and compare it (timing‑safe) with the X-FUNDSVERA-SIGNATURE header. If they match, the webhook is genuine.

Always return HTTP 200 after processing the webhook to acknowledge receipt. If you return any other status, Fundsvera may retry the delivery.

Verification Code Examples

<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_FUNDSVERA_SIGNATURE'] ?? '';
$secret = 'YOUR_SECRET_KEY'; // Business secret key

$computed = hash_hmac('sha256', $payload, $secret);
if (hash_equals($computed, $signature)) {
    // Trusted – process the webhook
    http_response_code(200);
    echo json_encode(['status' => 'received']);
} else {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}
?>
const crypto = require('crypto');

function verify(payload, signature, secret) {
    const computed = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
    return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signature));
}

app.post('/webhook', (req, res) => {
    const payload = JSON.stringify(req.body);
    const signature = req.headers['x-fundsvera-signature'];
    if (!verify(payload, signature, 'YOUR_SECRET_KEY')) {
        return res.status(401).json({ error: 'Invalid signature' });
    }
    // Process event...
    res.status(200).json({ status: 'received' });
});
import hmac, hashlib

def verify(payload, signature, secret):
    computed = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_data(as_text=True)
    signature = request.headers.get('X-FUNDSVERA-SIGNATURE', '')
    if not verify(payload, signature, 'YOUR_SECRET_KEY'):
        return jsonify({'error': 'Invalid signature'}), 401
    # Process event...
    return jsonify({'status': 'received'}), 200

Bank Transfer Webhook

When a bank transfer is successfully received, Fundsvera sends a bank_transfer.completed event to the webhook URL configured in your business profile. You must return HTTP 200 after processing to acknowledge receipt.

Webhook Payload Example

{
    "status": "SUCCESS",
    "transaction_status": "SUCCESSFUL",
    "trx_ref": "Btrf...",
    "request_id": "unique-ref-1234567890abcdefghijk",
    "amount_paid": 5000,
    "settlement_amount": 4875,
    "fee": 125,
    "trx_type": "checkout",
    "payer": {
        "name": "Bolaji Ola",
        "account_no": "1234567890",
        "bank_name": "Bank Name"
    },
    "customer": {
        "email": "[email protected]",
        "name": "Bolaji Ola",
        "virtual_account_no": "1234567890",
        "bank_name": "Palmpay",
        "phone": "08012345678"
    },
    "message": "Your payment has been successfully processed.",
    "created_date": "2026-06-04T10:30:00Z"
}

Webhook Handler Code

<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_FUNDSVERA_SIGNATURE'] ?? '';
$secret = 'YOUR_SECRET_KEY'; // Business secret key

$computed = hash_hmac('sha256', $payload, $secret);
if (!hash_equals($computed, $signature)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$data = json_decode($payload, true);
if ($data['transaction_status'] === 'SUCCESSFUL') {
    $trx = $data;
    // Validate request_id against your database
    // Update order status to paid
    // Grant value to customer

    error_log("Bank transfer completed: {$trx['trx_ref']} for {$trx['amount_paid']}");
    http_response_code(200);
    echo json_encode(['status' => 'received']);
} else {
    http_response_code(200);
    echo json_encode(['status' => 'ignored']);
}
?>
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());
const SECRET = 'YOUR_SECRET_KEY';

function verify(payload, signature) {
    const computed = crypto.createHmac('sha256', SECRET).update(payload).digest('hex');
    return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signature));
}

app.post('/webhook', (req, res) => {
    const payload = JSON.stringify(req.body);
    const signature = req.headers['x-fundsvera-signature'];
    if (!verify(payload, signature)) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = req.body;
    if (event.transaction_status === 'SUCCESSFUL') {
        const { trx_ref, request_id, amount_paid, customer } = event;
        console.log(`✅ Payment: ${amount_paid} for ${customer.email}`);
        // Update database, grant access, etc.
        return res.status(200).json({ status: 'received' });
    }
    res.status(200).json({ status: 'ignored' });
});

app.listen(3000);
from flask import Flask, request, jsonify
import hmac, hashlib

app = Flask(__name__)
SECRET = 'YOUR_SECRET_KEY'

def verify(payload, signature):
    computed = hmac.new(SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_data(as_text=True)
    signature = request.headers.get('X-FUNDSVERA-SIGNATURE', '')
    if not verify(payload, signature):
        return jsonify({'error': 'Invalid signature'}), 401

    data = request.get_json()
    if data.get('transaction_status') == 'SUCCESSFUL':
        print(f"Payment received: {data['amount_paid']} from {data['customer']['email']}")
        # Update your database
        return jsonify({'status': 'received'}), 200
    return jsonify({'status': 'ignored'}), 200

if __name__ == '__main__':
    app.run(port=3000)

Virtual Account Webhook

When a virtual account receives a payment, Fundsvera sends an event to your webhook URL configured in your business profile. Always return HTTP 200 after successful processing.

Payment Received Webhook (Example)

{
    "status": "SUCCESS",
    "transaction_status": "SUCCESSFUL",
    "trx_ref": "Tref...",
    "amount_paid": 5000,
    "settlement_amount": 4875,
    "fee": 125,
    "payer": {
        "name": "Sender Name",
        "account_no": "9876543210",
        "bank_name": "Sender Bank"
    },
    "customer": {
        "email": "[email protected]",
        "virtual_account_no": "1234567890",
        "bank_name": "Palmpay",
        "phone": "08012345678"
    },
    "message": "Your payment has been successfully processed.",
    "created_date": "2026-06-04T10:30:00Z"
}

Webhook Handler Code

<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_FUNDSVERA_SIGNATURE'] ?? '';
$secret = 'YOUR_SECRET_KEY';

$computed = hash_hmac('sha256', $payload, $secret);
if (!hash_equals($computed, $signature)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$data = json_decode($payload, true);
if ($data['transaction_status'] === 'SUCCESSFUL') {
    // Handle successful payment to a virtual account
    $va = $data['customer']['virtual_account_no'];
    $amount = $data['amount_paid'];
    error_log("Virtual account {$va} funded with {$amount}");
    http_response_code(200);
    echo json_encode(['status' => 'received']);
} else {
    http_response_code(200);
    echo json_encode(['status' => 'ignored']);
}
?>
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());
const SECRET = 'YOUR_SECRET_KEY';

function verify(payload, signature) {
    const computed = crypto.createHmac('sha256', SECRET).update(payload).digest('hex');
    return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signature));
}

app.post('/webhook', (req, res) => {
    const payload = JSON.stringify(req.body);
    const signature = req.headers['x-fundsvera-signature'];
    if (!verify(payload, signature)) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = req.body;
    if (event.transaction_status === 'SUCCESSFUL') {
        const { virtual_account_no } = event.customer;
        console.log(`Virtual account ${virtual_account_no} credited with ${event.amount_paid}`);
        return res.status(200).json({ status: 'received' });
    }
    res.status(200).json({ status: 'ignored' });
});

app.listen(3000);
from flask import Flask, request, jsonify
import hmac, hashlib

app = Flask(__name__)
SECRET = 'YOUR_SECRET_KEY'

def verify(payload, signature):
    computed = hmac.new(SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_data(as_text=True)
    signature = request.headers.get('X-FUNDSVERA-SIGNATURE', '')
    if not verify(payload, signature):
        return jsonify({'error': 'Invalid signature'}), 401

    data = request.get_json()
    if data.get('transaction_status') == 'SUCCESSFUL':
        va = data['customer']['virtual_account_no']
        print(f"Virtual account {va} funded with {data['amount_paid']}")
        return jsonify({'status': 'received'}), 200
    return jsonify({'status': 'ignored'}), 200

if __name__ == '__main__':
    app.run(port=3000)

Code Samples

Ready-to-use code examples for integrating with Fundsvera API.

Free Integration Support

Can't figure out the integration? Our team will help you for FREE!

Schedule Free Integration Help

Create Virtual Account

<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://fundsvera.co/api/v1/create-virtual-account',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_SECRET_KEY',
        'Public-Key: YOUR_PUBLIC_KEY',
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'email' => '[email protected]',
        'name' => 'Bolaji Olami',
        'bank_code' => '100033',
        'phone' => '08012345678'
    ])
]);

$response = curl_exec($curl);
curl_close($curl);
?>
const axios = require('axios');

async function createVA() {
    const res = await axios.post(
        'https://fundsvera.co/api/v1/create-virtual-account',
        {
            email: '[email protected]',
            name: 'Bolaji Olami',
            bank_code: '100033',
            phone: '08012345678'
        },
        {
            headers: {
                'Authorization': 'Bearer YOUR_SECRET_KEY',
                'Public-Key': 'YOUR_PUBLIC_KEY',
                'Content-Type': 'application/json'
            }
        }
    );
    console.log(res.data);
}
createVA();
import requests

url = "https://fundsvera.co/api/v1/create-virtual-account"
headers = {
    "Authorization": "Bearer YOUR_SECRET_KEY",
    "Public-Key": "YOUR_PUBLIC_KEY",
    "Content-Type": "application/json"
}
payload = {
    "email": "[email protected]",
    "name": "Bolaji Olami",
    "bank_code": "100033",
    "phone": "08012345678"
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())
curl -X POST https://fundsvera.co/api/v1/create-virtual-account \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Public-Key: YOUR_PUBLIC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "name": "Bolaji Olami",
    "bank_code": "100033",
    "phone": "08012345678"
  }'

Initiate Bank Transfer

<?php
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => 'https://fundsvera.co/api/v1/secured-checkout',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_SECRET_KEY',
        'Public-Key: YOUR_PUBLIC_KEY',
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'customer_email' => '[email protected]',
        'customer_name' => 'Bolaji Ola',
        'amount' => 5000,
        'request_id' => 'unique-ref-1234567890abcdefghijk',
        'redirect_url' => 'https://your-website.com/sucess-page'
    ])
]);
$response = curl_exec($curl);
curl_close($curl);
?>
const axios = require('axios');

async function initBankTransfer() {
    const res = await axios.post(
        'https://fundsvera.co/api/v1/secured-checkout',
        {
            customer_email: '[email protected]',
            customer_name: 'Bolaji Ola',
            amount: 5000,
            request_id: 'unique-ref-1234567890abcdefghijk',
            redirect_url: 'https://your-website.com/sucess-page'
        },
        {
            headers: {
                'Authorization': 'Bearer YOUR_SECRET_KEY',
                'Public-Key': 'YOUR_PUBLIC_KEY',
                'Content-Type': 'application/json'
            }
        }
    );
    console.log(res.data);
}
initBankTransfer();
import requests

url = "https://fundsvera.co/api/v1/secured-checkout"
headers = {
    "Authorization": "Bearer YOUR_SECRET_KEY",
    "Public-Key": "YOUR_PUBLIC_KEY",
    "Content-Type": "application/json"
}
payload = {
    "customer_email": "[email protected]",
    "customer_name": "Bolaji Ola",
    "amount": 5000,
    "request_id": "unique-ref-1234567890abcdefghijk",
    "redirect_url": "https://your-website.com/sucess-page"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
curl -X POST https://fundsvera.co/api/v1/secured-checkout \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Public-Key: YOUR_PUBLIC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_email": "[email protected]",
    "customer_name": "Bolaji Ola",
    "amount": 5000,
    "request_id": "unique-ref-1234567890abcdefghijk",
    "redirect_url": "https://your-website.com/sucess-page"
  }'

Coming Soon

Upcoming Features

  • 📊 Transaction History - Retrieve detailed transaction history
  • 💰 Balance Inquiry - Check virtual account balances
  • 🔄 Bulk Operations - Create multiple accounts at once
  • 📱 USSD Integration - USSD payment capabilities
  • 📈 Analytics & Reporting - Advanced analytics dashboard

Be the first to know!

Subscribe to our newsletter for early access to new features.

Notify Me

Error Codes

HTTP Status Codes

StatusCodeDescription
200OKRequest successful
400Bad RequestInvalid parameters
401UnauthorizedInvalid API keys
403ForbiddenInsufficient permissions
404Not FoundResource not found
500Server ErrorInternal server issue

Still having issues?

Our support team is available 24/7 to help you resolve any errors.

Get Free Support