Skip to content
Payfim - Secure. Simple. Yours.
Developers

REST API & webhooks

Connect any custom website to Payfim with two API calls and one webhook.

PFPayfim Team · September 28, 2026 · 8 min read

Authentication

Send your API key (Gateway dashboard → Integrations) in the X-Payfim-Api-Key header. Always call the API from your server, never from a browser.

Create an invoice

POST https://yourdomain.com/payfim/api.php?action=create_invoice
X-Payfim-Api-Key: pf_live_xxx

order_id=1001&amount=49.99&currency=USD
&webhook_url=https://yourstore.com/payfim-webhook
&return_url=https://yourstore.com/thank-you
&cancel_url=https://yourstore.com/cart
&customer_email=buyer@example.com&description=Order+1001

Response:

{"status":"success","invoice":{"id":"3f1c...","status":"new","checkout_url":"https://yourdomain.com/payfim/checkout.php?i=3f1c...", ...}}

Redirect your customer to checkout_url. Calling create_invoice again with the same order_id, amount and webhook URL returns the same open invoice (idempotent).

FieldRequiredNotes
order_idyesYour order reference (letters, digits, - _ # . : /)
amountyesDecimal, e.g. 49.99
currencynoISO code, defaults to the gateway currency
webhook_urlrecommendedMust be a public https URL
return_url / cancel_urlnoWhere to send the customer afterwards
coinnoPre-select a coin, e.g. USDT_TRC20
metadatanoJSON object echoed back in webhooks

Get an invoice

GET https://yourdomain.com/payfim/api.php?action=get_invoice&id=3f1c...
X-Payfim-Api-Key: pf_live_xxx

Statuses: new, pending, confirming, paid, underpaid, expired, cancelled.

Webhooks

Payfim POSTs JSON to your webhook_url when the status changes, with the header X-Payfim-Signature: t=TIMESTAMP,v1=HEX. Verify it like this:

$raw = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_X_PAYFIM_SIGNATURE'] ?? ''), $sig);
$ok = isset($sig['t'], $sig['v1'])
   && abs(time() - (int) $sig['t']) < 300
   && hash_equals(hash_hmac('sha256', $sig['t'] . '.' . $raw, 'pf_live_xxx'), $sig['v1']);
if (!$ok) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// Best practice: re-fetch the invoice with get_invoice before fulfilling the order.
if ($event['status'] === 'paid') { /* mark order paid */ }
http_response_code(200);

Respond with HTTP 2xx. Failed deliveries are retried after 1, 5 and 15 minutes, then 1, 3, 6, 12 and 24 hours.

Accept crypto on your store today

Self-hosted, non-custodial, zero fees. Lifetime license.