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.
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.
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));import crypto from 'crypto';
function sig(...fields) {
const nonEmpty = fields.filter(v => v !== undefined && v !== null && v !== '');
return crypto.createHash('sha256').update(nonEmpty.join('|')).digest('hex');
}import hashlib
def sig(*fields):
parts = [str(f) for f in fields if f not in (None, '')]
return hashlib.sha256('|'.join(parts).encode()).hexdigest()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ą.
Pola żądania
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| shopId | int | wymagane | Identyfikator sklepu z panelu. |
| price | number | wymagane | Kwota do zapłaty, dwa miejsca po przecinku. |
| control | string | opcjonalne | Twój własny identyfikator zamówienia. Wraca w powiadomieniu. |
| description | string | opcjonalne | Opis widoczny dla kupującego. |
| string | opcjonalne | Adres kupującego — wyślemy na niego potwierdzenie. | |
| notifyURL | url | opcjonalne | Adres, pod który wyślemy powiadomienie o płatności. |
| returnUrlSuccess | url | opcjonalne | Adres powrotu po udanej płatności. |
| returnUrlSuccessTidPass | bool | opcjonalne | Gdy ustawione, do adresu powrotu dopiszemy tid. |
| hideReceiver | bool | opcjonalne | Ukrywa dane odbiorcy na stronie płatności. |
| customFinishNote | string | opcjonalne | Własna informacja na ekranie końcowym. |
| signature | string | wymagane | Podpis żądania. |
Kolejność pól w podpisie
SECRET_KEY|shopId|price|control|description|email|notifyURL|returnUrlSuccessPrzykł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'];const price = (29.70).toFixed(2);
const control = 'order-123';
const notifyURL = 'https://example.com/pbl/notify';
const returnUrlSuccess = 'https://example.com/dziekujemy';
const signature = sig(SECRET, SHOP_ID, price, control, '', '', notifyURL, returnUrlSuccess);
const res = await fetch('https://secure.paybylink.pl/api/v1/transfer/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
shopId: SHOP_ID,
price: Number(price),
control, notifyURL, returnUrlSuccess, signature
})
});
console.log(await res.json());curl -X POST https://secure.paybylink.pl/api/v1/transfer/generate \
-H 'Content-Type: application/json' \
-d '{"shopId":1234,"price":29.70,"control":"order-123","signature":"..."}'Odpowiedź
{
"url": "https://secure.pbl.pl/transfer/XYZ...",
"transactionId": "XYZ..."
}Anulowanie transakcji
Anuluje transakcję, która nie została jeszcze opłacona.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| shopId | int | wymagane | Identyfikator sklepu. |
| transactionId | string | wymagane | Identyfikator transakcji zwrócony przy generowaniu. |
| customReason | string | opcjonalne | Powód anulowania, widoczny w panelu. |
| signature | string | wymagane | Podpis żądania. |
Kolejność pól w podpisie
SECRET_KEY|shopId|transactionId|customReasonOdpowiedź
{ "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ę.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| shopId | int | wymagane | Identyfikator sklepu. |
| price | number | wymagane | Kwota, dwa miejsca po przecinku. |
| code | string | wymagane | Sześciocyfrowy kod z aplikacji bankowej kupującego. |
| customerIP | string | wymagane | Adres IP kupującego inicjującego płatność. |
| control | string | opcjonalne | Twój identyfikator zamówienia. |
| notifyPaymentURL | url | opcjonalne | Adres powiadomienia o zaksięgowaniu płatności. |
| notifyStatusURL | url | opcjonalne | Adres powiadomienia o statusie autoryzacji BLIK. |
| signature | string | wymagane | Podpis żądania. |
Kolejność pól w podpisie
SECRET_KEY|shopId|price|code|customerIP|control|notifyPaymentURL|notifyStatusURLOdpowiedź
{ "transactionId": "w3WUQX...JLJ" }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.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| transactionId | string | wymagane | Identyfikator transakcji, 32 znaki. |
| control | string | opcjonalne | Wartość, którą przekazałeś przy generowaniu. |
| string | opcjonalne | Adres kupującego. | |
| amountPaid | number | wymagane | Kwota zaksięgowana, dwa miejsca po przecinku. |
| notificationAttempt | int | wymagane | Numer próby doręczenia. |
| paymentType | string | wymagane | Rodzaj płatności, na przykład TRANSFER. |
| apiVersion | int | wymagane | Wersja API. |
| signature | string | wymagane | Podpis do weryfikacji. |
Kolejność pól w podpisie
SECRET_KEY|transactionId|control|email|amountPaid|notificationAttempt|paymentType|apiVersionPotwierdzenie 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.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| transactionId | string | wymagane | Identyfikator transakcji. |
| control | string | opcjonalne | Twój identyfikator zamówienia. |
| price | string | wymagane | Kwota, dwa miejsca po przecinku. |
| status | string | wymagane | Wynik autoryzacji. |
| signature | string | wymagane | Podpis 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|statusSMS 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.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| userid | int | wymagane | Numer identyfikacyjny partnera w panelu. |
| serviceid | int | wymagane | Numer identyfikacyjny kanału SMS Premium. |
| code | string | wymagane | Kod zwrotny otrzymany przez kupującego. |
| number | string | wymagane | Numer, na który wysłano wiadomość. |
Odpowiedź
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| status | string | opcjonalne | Informacja, czy kod jest aktywny. |
| service | int | opcjonalne | Identyfikator kanału SMS użytego w zapytaniu. |
| phone | string | opcjonalne | Numer telefonu, z którego dokonano płatności. |
| reply | string | opcjonalne | Treść 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 zapytaniuSMS Premium — weryfikacja wielocenowa
Wariant zalecany, gdy sprzedajesz produkty w różnych cenach. Nie wymaga podania numeru — zwraca go w odpowiedzi.
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| userid | int | wymagane | Numer identyfikacyjny partnera w panelu. |
| serviceid | int | wymagane | Numer identyfikacyjny kanału SMS Premium. |
| code | string | wymagane | Kod zwrotny otrzymany przez kupującego. |
Odpowiedź
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
| status | string | opcjonalne | Informacja, czy kod jest aktywny. |
| service | int | opcjonalne | Identyfikator kanału SMS. |
| phone | string | opcjonalne | Numer telefonu kupującego. |
| number | string | opcjonalne | Numer, na który wysłano wiadomość. |
| reply | string | opcjonalne | Treść 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.