Getting StartedQuick Start

Quick Start

Make your first payment in under 5 minutes using the POPFAB API.

1Create an account

Sign up at popfab.io/signup to get your merchant account. Once registered, navigate to API Keys in the dashboard to generate a test key.

Your sandbox key starts with sk_test_. No real money moves in sandbox — all provider responses are simulated.

2Initiate a payment

Send a POST /v1/payments request with your API key in the Authorization header. Always include a unique Idempotency-Key to prevent duplicate charges.

Initiate a payment — cURLbash
curl -X POST https://api.popfab.io/v1/payments \
  -H "Authorization: Bearer sk_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_12345_attempt_1" \
  -d '{
    "amount": 50000,
    "currency": "NGN",
    "payment_method": "card",
    "reference": "ORD-12345",
    "customer": {
      "email": "john@example.com",
      "name": "John Doe"
    },
    "metadata": {
      "order_id": "ORD-12345"
    }
  }'
Initiate a payment — Node.jsjavascript
const response = await fetch('https://api.popfab.io/v1/payments', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_test_YOUR_API_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order_12345_attempt_1',
  },
  body: JSON.stringify({
    amount: 50000,        // in kobo (₦500.00)
    currency: 'NGN',
    payment_method: 'card',
    reference: 'ORD-12345',
    customer: {
      email: 'john@example.com',
      name: 'John Doe',
    },
    metadata: {
      order_id: 'ORD-12345',
    },
  }),
});

const payment = await response.json();
if (payment.checkout_url) {
  // Send this URL to your frontend and redirect the customer there.
  console.log('Redirect customer to:', payment.checkout_url);
}

3Handle the response

A successful request returns a payment object. The initial status is usually pending or processing. Listen for a webhook event to know the final outcome.

Payment responsejson
{
  "id": "ppfb_pay_01HX9T2KBQM4Z3YWN5E6R7VP8S",
  "merchant_id": "ppfb_merch_01HX8W7K4YR6E9N2M3Q5T1ABCD",
  "idempotency_key": "order_12345_attempt_1",
  "reference": "ORD-12345",
  "amount": 50000,
  "currency": "NGN",
  "payment_method": "card",
  "status": "pending",
  "provider": "paystack",
  "provider_reference": "psk_T8x29kLMqpn",
  "checkout_url": "https://checkout.paystack.com/abc123",
  "customer": {
    "email": "john@example.com",
    "name": "John Doe"
  },
  "metadata": { "order_id": "ORD-12345" },
  "fees": {
    "popfabFee": 75,
    "providerFee": 125,
    "totalFee": 200
  },
  "routing_context": {
    "strategy": "success_rate",
    "providersConsidered": ["paystack", "flutterwave"],
    "selectedProvider": "paystack",
    "selectionReason": "highest_success_rate",
    "attempts": [
      {
        "provider": "paystack",
        "attemptedAt": "2025-03-19T10:23:45.000Z",
        "outcome": "success",
        "latencyMs": 284
      }
    ]
  },
  "failure_reason": null,
  "created_at": "2025-03-19T10:23:45.000Z",
  "updated_at": "2025-03-19T10:23:45.000Z"
}
Redirect the customer to checkout_url when it is present. It is conditional because not every payment method uses a hosted checkout page. Confirm the final result using webhooks orGET /v1/payments/:id; do not treat the customer's browser redirect as proof of payment.

4Set up a webhook

Register a webhook endpoint to receive real-time payment status updates. POPFAB delivers signed events with at-least-once guarantees and automatic retries.

Register a webhook endpointbash
curl -X POST https://api.popfab.io/v1/webhooks/endpoints \
  -H "Authorization: Bearer sk_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/popfab",
    "events": ["payment.success", "payment.failed"],
    "enabled": true
  }'
Verify and handle webhook eventsjavascript
import crypto from 'crypto';

export async function POST(req) {
  const body = await req.text();
  const signature = req.headers.get('X-POPFAB-Signature');
  const webhookSecret = process.env.POPFAB_WEBHOOK_SECRET;

  // Verify signature
  const expected = crypto
    .createHmac('sha256', webhookSecret)
    .update(body)
    .digest('hex');

  if (signature !== `sha256=${expected}`) {
    return new Response('Unauthorized', { status: 401 });
  }

  const event = JSON.parse(body);

  if (event.event === 'payment.success') {
    const payment = event.data;
    // Fulfill the order
    await fulfillOrder(payment.metadata.order_id);
  }

  return new Response('OK', { status: 200 });
}

5Go live

When you're ready to accept real payments, generate a live API key (sk_live_...) from the dashboard. No code changes needed — just swap the key.

Live keys move real money. Never expose them in client-side code, browser logs, or public repositories. Use environment variables.