Dokumentacja API

Wszystko, czego potrzebujesz, żeby przyjmować przelewy online i BLIK we własnym sklepie. Wersja API 1.3.

Wszystkie żądania wysyłasz metodą POST z ciałem w formacie JSON i nagłówkiem Content-Type: application/json. Kodowanie to UTF-8.

BASE https://secure.paybylink.pl

Identyfikator sklepu (shopId) oraz klucz tajny (SECRET_KEY) znajdziesz w panelu, w konfiguracji sklepu. Klucz tajny nigdy nie opuszcza Twojego serwera — nie umieszczaj go w kodzie strony ani w aplikacji mobilnej.

Masz pytanie techniczne? Napisz na [email protected] — odpowiadamy w dni robocze.

Podpis żądania

Każde żądanie i każdy webhook zawiera pole signature. To skrót SHA-256 (zapisany szesnastkowo) z połączonych wartości, rozdzielonych znakiem |.

  • Pierwszym elementem jest zawsze Twój klucz tajny.
  • Pola puste pomijasz w całości — nie zostawiasz po nich pustego miejsca.
  • Kolejność pól jest ustalona osobno dla każdej metody i musi być zachowana.
  • Kwoty podajesz zawsze z dwoma miejscami po przecinku, na przykład 10.00.
$parts = array_filter([
  $secretKey,
  $shopId,
  $price,
  $control,
  $description,
  $email,
  $notifyURL,
  $returnUrlSuccess
], fn($v) => $v !== null && $v !== '');

$signature = hash('sha256', implode('|', $parts));
Zawsze sprawdzaj podpis w webhookach zanim zmienisz status zamówienia. Bez tego każdy, kto zna Twój adres powiadomień, mógłby oznaczyć zamówienie jako opłacone.

Błędy

Gdy żądanie się nie powiedzie, odpowiedź zawiera kod i opis błędu.

{
  "errorCode": 403,
  "error": "invalid signature"
}

Sprawdzaj obecność pola errorCode w odpowiedzi — jego brak oznacza, że operacja się powiodła.

Wygenerowanie płatności

Tworzy link do strony płatności. Przekierowujesz na niego kupującego, a my zajmujemy się resztą.

POST /api/v1/transfer/generate

Pola żądania

PoleTypWymaganeOpis
shopIdintwymaganeIdentyfikator sklepu z panelu.
pricenumberwymaganeKwota do zapłaty, dwa miejsca po przecinku.
controlstringopcjonalneTwój własny identyfikator zamówienia. Wraca w powiadomieniu.
descriptionstringopcjonalneOpis widoczny dla kupującego.
emailstringopcjonalneAdres kupującego — wyślemy na niego potwierdzenie.
notifyURLurlopcjonalneAdres, pod który wyślemy powiadomienie o płatności.
returnUrlSuccessurlopcjonalneAdres powrotu po udanej płatności.
returnUrlSuccessTidPassboolopcjonalneGdy ustawione, do adresu powrotu dopiszemy tid.
hideReceiverboolopcjonalneUkrywa dane odbiorcy na stronie płatności.
customFinishNotestringopcjonalneWłasna informacja na ekranie końcowym.
signaturestringwymaganePodpis żądania.

Kolejność pól w podpisie

SECRET_KEY|shopId|price|control|description|email|notifyURL|returnUrlSuccess

Przykład

$price = number_format(29.70, 2, '.', '');
$control = 'order-123';
$description = 'Zamówienie 123';
$email = '[email protected]';
$notifyURL = 'https://example.com/pbl/notify';
$returnUrlSuccess = 'https://example.com/dziekujemy';

$parts = array_filter([
  $secretKey, $shopId, $price, $control,
  $description, $email, $notifyURL, $returnUrlSuccess
], fn($v) => $v !== null && $v !== '');

$payload = [
  'shopId' => $shopId,
  'price' => (float) $price,
  'control' => $control,
  'description' => $description,
  'email' => $email,
  'notifyURL' => $notifyURL,
  'returnUrlSuccess' => $returnUrlSuccess,
  'signature' => hash('sha256', implode('|', $parts))
];

$ch = curl_init('https://secure.paybylink.pl/api/v1/transfer/generate');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
]);

$data = json_decode(curl_exec($ch), true);
echo $data['url'];

Odpowiedź

{
  "url": "https://secure.pbl.pl/transfer/XYZ...",
  "transactionId": "XYZ..."
}

Anulowanie transakcji

Anuluje transakcję, która nie została jeszcze opłacona.

POST /api/v1/transfer/cancel
PoleTypWymaganeOpis
shopIdintwymaganeIdentyfikator sklepu.
transactionIdstringwymaganeIdentyfikator transakcji zwrócony przy generowaniu.
customReasonstringopcjonalnePowód anulowania, widoczny w panelu.
signaturestringwymaganePodpis żądania.

Kolejność pól w podpisie

SECRET_KEY|shopId|transactionId|customReason

Odpowiedź

{ "cancelled": true }

{ "cancelled": false, "cancelError": "Transaction already cancelled" }

BLIK white-label

Kupujący wpisuje sześciocyfrowy kod BLIK bezpośrednio w Twoim koszyku, a autoryzacja przebiega w tle — bez przenoszenia go na naszą stronę.

POST /api/v1/transfer/blikauth
PoleTypWymaganeOpis
shopIdintwymaganeIdentyfikator sklepu.
pricenumberwymaganeKwota, dwa miejsca po przecinku.
codestringwymaganeSześciocyfrowy kod z aplikacji bankowej kupującego.
customerIPstringwymaganeAdres IP kupującego inicjującego płatność.
controlstringopcjonalneTwój identyfikator zamówienia.
notifyPaymentURLurlopcjonalneAdres powiadomienia o zaksięgowaniu płatności.
notifyStatusURLurlopcjonalneAdres powiadomienia o statusie autoryzacji BLIK.
signaturestringwymaganePodpis żądania.

Kolejność pól w podpisie

SECRET_KEY|shopId|price|code|customerIP|control|notifyPaymentURL|notifyStatusURL

Odpowiedź

{ "transactionId": "w3WUQX...JLJ" }
Kod BLIK jest jednorazowy i ważny krótko. Wyślij żądanie od razu po jego pobraniu i nigdy nie zapisuj go w logach.

Webhook płatności

Jeśli podałeś notifyURL, po zaksięgowaniu wpłaty wyślemy pod ten adres żądanie POST z ciałem JSON.

PoleTypWymaganeOpis
transactionIdstringwymaganeIdentyfikator transakcji, 32 znaki.
controlstringopcjonalneWartość, którą przekazałeś przy generowaniu.
emailstringopcjonalneAdres kupującego.
amountPaidnumberwymaganeKwota zaksięgowana, dwa miejsca po przecinku.
notificationAttemptintwymaganeNumer próby doręczenia.
paymentTypestringwymaganeRodzaj płatności, na przykład TRANSFER.
apiVersionintwymaganeWersja API.
signaturestringwymaganePodpis do weryfikacji.

Kolejność pól w podpisie

SECRET_KEY|transactionId|control|email|amountPaid|notificationAttempt|paymentType|apiVersion

Potwierdzenie odbioru

Odpowiedz kodem 200 i treścią OK o typie text/plain. Brak potwierdzenia oznacza ponawianie z rosnącym odstępem, maksymalnie 241 razy.

$body = json_decode(file_get_contents('php://input'), true);

$parts = array_filter([
  $secretKey,
  $body['transactionId'],
  $body['control'],
  $body['email'],
  number_format($body['amountPaid'], 2, '.', ''),
  $body['notificationAttempt'],
  $body['paymentType'],
  $body['apiVersion']
], fn($v) => $v !== null && $v !== '');

if (!hash_equals(hash('sha256', implode('|', $parts)), $body['signature'])) {
  http_response_code(403);
  exit;
}

header('Content-Type: text/plain');
echo 'OK';

Webhook statusu BLIK

Przy autoryzacji white-label pod adres notifyStatusURL wysyłamy wynik potwierdzenia kodu przez kupującego.

PoleTypWymaganeOpis
transactionIdstringwymaganeIdentyfikator transakcji.
controlstringopcjonalneTwój identyfikator zamówienia.
pricestringwymaganeKwota, dwa miejsca po przecinku.
statusstringwymaganeWynik autoryzacji.
signaturestringwymaganePodpis do weryfikacji.

Możliwe statusy

{ "transactionId":"...", "price":"1.01", "status":"CONFIRMED" }
{ "transactionId":"...", "price":"1.01", "status":"TIMEOUT" }
{ "transactionId":"...", "price":"1.01", "status":"USER_DECLINED" }
{ "transactionId":"...", "price":"1.01", "status":"WRONG_TICKET" }

Kolejność pól w podpisie

SECRET_KEY|transactionId|control|price|status

SMS Premium — weryfikacja kodu

Sprawdza poprawność kodu zwrotnego, który kupujący otrzymał po wysłaniu wiadomości. Parametry przekazujesz metodą GET, odpowiedź wraca w JSON. Wariant dla produktów w jednej cenie.

GET https://www.paybylink.pl/api/v2/index.php
PoleTypWymaganeOpis
useridintwymaganeNumer identyfikacyjny partnera w panelu.
serviceidintwymaganeNumer identyfikacyjny kanału SMS Premium.
codestringwymaganeKod zwrotny otrzymany przez kupującego.
numberstringwymaganeNumer, na który wysłano wiadomość.

Odpowiedź

PoleTypWymaganeOpis
statusstringopcjonalneInformacja, czy kod jest aktywny.
serviceintopcjonalneIdentyfikator kanału SMS użytego w zapytaniu.
phonestringopcjonalneNumer telefonu, z którego dokonano płatności.
replystringopcjonalneTreść wiadomości zwrotnej wysłanej do kupującego.

Komunikaty błędów

"Connection error"              // błędne dane wejściowe
"Code does not exist"           // brak kodu w zapytaniu
"User or service does not exist" // zły kanał lub partner
"Number does not exist"         // brak numeru w zapytaniu

SMS Premium — weryfikacja wielocenowa

Wariant zalecany, gdy sprzedajesz produkty w różnych cenach. Nie wymaga podania numeru — zwraca go w odpowiedzi.

GET https://www.paybylink.pl/api/v2/multi.php
PoleTypWymaganeOpis
useridintwymaganeNumer identyfikacyjny partnera w panelu.
serviceidintwymaganeNumer identyfikacyjny kanału SMS Premium.
codestringwymaganeKod zwrotny otrzymany przez kupującego.

Odpowiedź

PoleTypWymaganeOpis
statusstringopcjonalneInformacja, czy kod jest aktywny.
serviceintopcjonalneIdentyfikator kanału SMS.
phonestringopcjonalneNumer telefonu kupującego.
numberstringopcjonalneNumer, na który wysłano wiadomość.
replystringopcjonalneTreść wiadomości zwrotnej.

Pliki i kolekcje

Gotowe materiały do wczytania w narzędziach, z których korzystasz na co dzień.

Środowisko testowe

Zanim uruchomisz sprzedaż, sprawdź wdrożenie na danych testowych.

Płatności

W panelu, w konfiguracji sklepu, włącz tryb testowy. Transakcje wykonane w tym trybie nie obciążają kupującego, ale przechodzą pełną ścieżkę razem z powiadomieniami, więc zweryfikujesz także obsługę webhooków.

SMS Premium

Każdy przyznany sufiks pozwala wygenerować kod testowy. Zaloguj się do panelu i przejdź do sekcji SMS Premium, następnie Konta SMS, wybierz sufiks i otwórz konfigurację — znajdziesz tam pozycję z kodem testowym.

Coś nie działa tak, jak opisano? Napisz na [email protected] i podaj identyfikator transakcji — sprawdzimy, co poszło nie tak.