Payxit Developer Documentation

Use Payxit to manage Nigerian payment gateways through a single API.

1) Overview

Payxit lets merchants manage multiple Nigerian payment gateways with a single API. Merchants generate Payxit API keys in the dashboard, then use those keys to create payment sessions for their customers. Customers are redirected to a Payxit-hosted public payment page and then routed to the selected gateway’s checkout flow (Flutterwave, Paystack, Opay, PalmPay, KongaPay, Moniepoint).

2) Base URLs

  • Production API: https://api.payxit.co/v1
  • Public pay page: https://payxit.co/pay/{token}

3) Authentication (Public Developer Access)

Payxit payment processing endpoints require a Payxit API public key in the request header.

  • Header: x-payxit-key
  • Alternate: x-api-key
POST /v1/payxit/public/payments HTTP/1.1
Host: api.payxit.co
Content-Type: application/json
x-payxit-key: pk_live_xxxxxxxxxxxxxxxxx

4) Payment Processing Flow

  1. Merchant creates a payment session using Payxit’s public API.
  2. Payxit returns a token and a public payment page redirect URL.
  3. Merchant redirects the customer to the Payxit payment page.
  4. Customer clicks “Proceed with Payment” to open gateway checkout.
  5. Gateway confirms payment via webhook callbacks.
  6. Payxit records the transaction and updates status.

5) Public Developer Endpoints

5.1 Health Check Public

GET /health

{ "status": "ok" }

5.2 List Supported Gateways Public

GET /v1/payxit/public/gateways

{ "gateways": [] }

5.3 Pricing Public

GET /v1/payxit/public/pricing

{ "pricing": [] }

5.4 Create Payment Session Auth

POST /v1/payxit/public/payments

Headers: x-payxit-key

{
  "name": "Ada Nwosu",
  "email": "ada@example.com",
  "phone": "+2348012345678",
  "amount": 25000,
  "currency": "NGN"
}
{
  "token": "ab12cd34ef56...",
  "redirectUrl": "https://payxit.co/pay/ab12cd34ef56...",
  "session": {
    "id": "uuid",
    "status": "created",
    "amount": 25000,
    "currency": "NGN",
    "customerName": "Ada Nwosu",
    "customerEmail": "ada@example.com",
    "customerPhone": "+2348012345678",
    "gateway": "flutterwave"
  }
}

5.5 Get Payment Session Public

GET /v1/payxit/public/payments/:token

{
  "session": {
    "id": "uuid",
    "status": "created",
    "amount": 25000,
    "currency": "NGN",
    "customerName": "Ada Nwosu",
    "customerEmail": "ada@example.com",
    "customerPhone": "+2348012345678",
    "gateway": "flutterwave",
    "checkoutUrl": null
  }
}

5.6 Initiate Payment Session Public

POST /v1/payxit/public/payments/:token/initiate

This is invoked by the Payxit payment page when a customer proceeds to the gateway checkout.

{
  "session": {
    "id": "uuid",
    "status": "initiated",
    "gateway": "flutterwave",
    "checkoutUrl": "https://gateway.example/checkout/xyz"
  }
}

5.7 Webhooks Gateway

POST /v1/webhooks/:gateway

Raw body is required. Payxit validates signatures and updates transactions based on gateway payloads.

6) Error Responses

{ "message": "Description of the error." }
  • 400 — invalid or missing fields
  • 401 — invalid API key
  • 404 — payment session not found
  • 409 — payment already initiated
  • 502 — gateway checkout URL not returned

7) Example Integration

curl -X POST "https://api.payxit.co/v1/payxit/public/payments" \
  -H "Content-Type: application/json" \
  -H "x-payxit-key: pk_live_xxxxxxxxxxxxx" \
  -d '{
    "name": "Ada Nwosu",
    "email": "ada@example.com",
    "phone": "+2348012345678",
    "amount": 25000,
    "currency": "NGN"
  }'

Redirect the customer to the returned redirectUrl, which will look like:

https://payxit.co/pay/{token}

8) React Checkout (Payment.jsx)

Use the component below to collect customer details and redirect to the Payxit checkout page. It matches docs/Payment.jsx.

import React, { useState } from 'react';
import axios from 'axios';

const Payment = () => {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    phone: '',
    amount: '',
    currency: 'NGN'
  });
  const [apiKey, setApiKey] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData((prev) => ({ ...prev, [name]: value }));
  };

  const handleApiKeyChange = (e) => {
    setApiKey(e.target.value);
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!apiKey) {
      setError('Please enter your Payxit API key.');
      return;
    }
    setLoading(true);
    setError('');
    try {
      const response = await axios.post('/v1/payxit/public/payments', formData, {
        headers: {
          'x-payxit-key': apiKey,
          'Content-Type': 'application/json'
        }
      });
      const { redirectUrl } = response.data;
      window.location.href = redirectUrl;
    } catch (err) {
      setError(err.response?.data?.message || 'Failed to create payment session. Please try again.');
      console.error(err);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg shadow-md">
      <h2 className="text-2xl font-bold mb-6 text-center">Payment Form</h2>
      {error && <p className="text-red-500 mb-4">{error}</p>}
      <form onSubmit={handleSubmit}>
        <div className="mb-4">
          <label className="block text-gray-700">Payxit API Key (pk_live_ or pk_sandbox_)</label>
          <input
            type="text"
            value={apiKey}
            onChange={handleApiKeyChange}
            required
            placeholder="Enter your Payxit public key"
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div className="mb-4">
          <label className="block text-gray-700">Name</label>
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
            required
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div className="mb-4">
          <label className="block text-gray-700">Email</label>
          <input
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            required
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div className="mb-4">
          <label className="block text-gray-700">Phone (e.g., +2348012345678)</label>
          <input
            type="tel"
            name="phone"
            value={formData.phone}
            onChange={handleChange}
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div className="mb-4">
          <label className="block text-gray-700">Amount</label>
          <input
            type="number"
            name="amount"
            value={formData.amount}
            onChange={handleChange}
            required
            min="0"
            step="0.01"
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div className="mb-4">
          <label className="block text-gray-700">Currency</label>
          <select
            name="currency"
            value={formData.currency}
            onChange={handleChange}
            className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="NGN">NGN</option>
            <option value="USD">USD</option>
            <option value="EUR">EUR</option>
            <option value="GBP">GBP</option>
          </select>
        </div>
        <button
          type="submit"
          disabled={loading}
          className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 disabled:opacity-50"
        >
          {loading ? 'Processing...' : 'Submit Payment'}
        </button>
      </form>
    </div>
  );
};

export default Payment;

9) Vanilla JS Checkout (HTML + JS)

If you are not using React, use this HTML form with a script that calls the Payxit public API and redirects to the checkout URL.

<form id="payxit-form">
  <label>Payxit API Key (pk_live_ or pk_sandbox_)</label>
  <input type="text" id="apiKey" required />

  <label>Name</label>
  <input type="text" id="name" required />

  <label>Email</label>
  <input type="email" id="email" required />

  <label>Phone (e.g., +2348012345678)</label>
  <input type="tel" id="phone" />

  <label>Amount</label>
  <input type="number" id="amount" min="0" step="0.01" required />

  <label>Currency</label>
  <select id="currency">
    <option value="NGN">NGN</option>
    <option value="USD">USD</option>
    <option value="EUR">EUR</option>
    <option value="GBP">GBP</option>
  </select>

  <button type="submit">Submit Payment</button>
</form>

<script>
  const form = document.getElementById('payxit-form');

  form.addEventListener('submit', async (event) => {
    event.preventDefault();

    const apiKey = document.getElementById('apiKey').value.trim();
    if (!apiKey) {
      alert('Please enter your Payxit API key.');
      return;
    }

    const payload = {
      name: document.getElementById('name').value.trim(),
      email: document.getElementById('email').value.trim(),
      phone: document.getElementById('phone').value.trim(),
      amount: Number(document.getElementById('amount').value),
      currency: document.getElementById('currency').value
    };

    try {
      const response = await fetch('/v1/payxit/public/payments', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-payxit-key': apiKey
        },
        body: JSON.stringify(payload)
      });

      if (!response.ok) {
        const errorBody = await response.json();
        throw new Error(errorBody.message || 'Failed to create payment session.');
      }

      const data = await response.json();
      window.location.href = data.redirectUrl;
    } catch (error) {
      alert(error.message || 'Failed to create payment session.');
    }
  });
</script>

10) Security Notes

  • Keep Payxit API keys secret.
  • Use HTTPS in production.
  • Rotate keys if exposed.
  • Use gateway-specific webhook signatures.

11) Environment Notes

  • Payxit supports Live and Sandbox environments.
  • Keys and webhook URLs are managed per environment.
  • Use the corresponding public key for each environment.