ResourcesSDKs & Libraries

SDKs & Libraries

Official POPFAB SDKs are in active development. In the meantime, the REST API works directly with any HTTP client.

Official Node.js and Python SDKs are planned for Phase 2 (Month 3–6). Track progress or request a language on our GitHub.

SDK Roadmap

LanguagePackageStatusETA
Node.js / TypeScriptnpm install popfabIn developmentMonth 3
Pythonpip install popfabIn developmentMonth 3
Gogo get github.com/popfab/goPlannedMonth 6–12
JavaMaven / GradlePlannedMonth 6–12
PHPcomposer require popfab/popfab-phpCommunityCommunity-driven

Using the REST API Directly

Until SDKs are available, you can use any HTTP client. Here are minimal wrappers to get started quickly.

Node.js (fetch)

popfab.js — minimal wrapperjavascript
// popfab.js
const BASE_URL = 'https://api.popfab.io/v1';

export class Popfab {
  constructor(apiKey) {
    this.apiKey = apiKey;
  }

  async request(method, path, body, idempotencyKey) {
    const headers = {
      Authorization: `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json',
    };
    if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey;

    const res = await fetch(`${BASE_URL}${path}`, {
      method,
      headers,
      body: body ? JSON.stringify(body) : undefined,
    });

    const data = await res.json();
    if (!res.ok) throw Object.assign(new Error(data.error.message), data.error);
    return data;
  }

  // Payments
  createPayment(payload, idempotencyKey) {
    return this.request('POST', '/payments', payload, idempotencyKey);
  }
  getPayment(id) {
    return this.request('GET', `/payments/${id}`);
  }
  listPayments(params = {}) {
    const qs = new URLSearchParams(params).toString();
    return this.request('GET', `/payments?${qs}`);
  }
  refundPayment(id, payload) {
    return this.request('POST', `/payments/${id}/refund`, payload);
  }

  // Routing rules
  createRoutingRule(payload) {
    return this.request('POST', '/routing-rules', payload);
  }
  listRoutingRules() {
    return this.request('GET', '/routing-rules');
  }

  // Providers
  listProviders() {
    return this.request('GET', '/providers');
  }

  // Webhooks
  registerWebhook(payload) {
    return this.request('POST', '/webhooks/endpoints', payload);
  }
  listWebhooks() {
    return this.request('GET', '/webhooks/endpoints');
  }
  replayDelivery(deliveryId) {
    return this.request('POST', `/webhooks/${deliveryId}/replay`);
  }
}

// Usage:
// import { Popfab } from './popfab.js';
// const client = new Popfab(process.env.POPFAB_API_KEY);
// const payment = await client.createPayment({ ... }, 'idempotency-key');

Python (httpx)

popfab.py — minimal wrapperpython
# popfab.py
import os
import httpx

BASE_URL = "https://api.popfab.io/v1"


class PopfabError(Exception):
    def __init__(self, code, message, request_id):
        super().__init__(message)
        self.code = code
        self.request_id = request_id


class Popfab:
    def __init__(self, api_key: str):
        self.api_key = api_key

    def _headers(self, idempotency_key: str | None = None) -> dict:
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        }
        if idempotency_key:
            headers["Idempotency-Key"] = idempotency_key
        return headers

    def _request(self, method, path, body=None, idempotency_key=None):
        with httpx.Client() as client:
            res = client.request(
                method,
                f"{BASE_URL}{path}",
                headers=self._headers(idempotency_key),
                json=body,
            )
        data = res.json()
        if res.is_error:
            err = data["error"]
            raise PopfabError(err["code"], err["message"], err["request_id"])
        return data

    # Payments
    def create_payment(self, payload: dict, idempotency_key: str) -> dict:
        return self._request("POST", "/payments", payload, idempotency_key)

    def get_payment(self, payment_id: str) -> dict:
        return self._request("GET", f"/payments/{payment_id}")

    def list_payments(self, **params) -> dict:
        qs = "&".join(f"{k}={v}" for k, v in params.items())
        return self._request("GET", f"/payments?{qs}")

    def refund_payment(self, payment_id: str, payload: dict) -> dict:
        return self._request("POST", f"/payments/{payment_id}/refund", payload)

    # Providers
    def list_providers(self) -> list:
        return self._request("GET", "/providers")

    # Webhooks
    def register_webhook(self, payload: dict) -> dict:
        return self._request("POST", "/webhooks/endpoints", payload)


# Usage:
# from popfab import Popfab
# client = Popfab(os.environ["POPFAB_API_KEY"])
# payment = client.create_payment({...}, idempotency_key="key-123")