Referencja API
REST API Placenie, wersja 2026-10-03. Ta strona jest generowana ze specyfikacji OpenAPI 3.1, tej samej, którą API oddaje pod /api/v1/openapi.json, więc opisuje dokładnie to, co robi serwer.
API bramki płatniczej placenie.pl: tworzysz płatność, kierujesz klienta na adres_platnosci, a wynik dostajesz webhookiem i możesz go w każdej chwili pobrać zapytaniem.
Podstawy #
- Adres bazowy:
https://placenie.pl/api. Wszystkie ścieżki poniżej są względem niego (np.POST https://placenie.pl/api/v1/platnosci). - Uwierzytelnianie: nagłówek
Authorization: Bearer <klucz>. Klucz testowy ma postaćplc_test_..., produkcyjnyplc_live_.... Klucz testowy widzi wyłącznie transakcje testowe, produkcyjny wyłącznie produkcyjne. Klucze wydajesz w panelu (Integracja). - Kwoty zawsze w groszach (najmniejszej jednostce waluty):
12900to 129,00 zł. Nigdy ułamki. - Treść zapytań: JSON (
Content-Type: application/json). Formularzapplication/x-www-form-urlencodedteż działa. - Odpowiedzi i błędy zawsze w JSON, także 404 na nieznanej ścieżce, 405, 429 i 500.
- Czas w ISO 8601 ze strefą (
2026-10-03T12:34:56+00:00).
Identyfikatory #
Każdy obiekt ma pole obiekt i identyfikator ze stałym prefiksem: płatność tr_, zwrot zw_, zdarzenie evt_, zapytanie req_.
Identyfikator zapytania #
Każda odpowiedź ma nagłówek X-Request-Id (np. req_k3j2h1g0f9e8d7c6b5a4z3y2). Przy błędzie ten sam identyfikator jest w ciele jako blad.zadanie_id. Podaj go wsparciu, gdy coś poszło nie tak.
Wersja API #
Wersja to data. Odpowiedź niesie nagłówek Placenie-Version z wersją, która ją obsłużyła. Możesz wskazać wersję nagłówkiem Placenie-Version w zapytaniu (dostępne: 2026-10-01, 2026-10-03). Nieznana wersja to błąd 400 wersja_nieznana. Nowe pola dochodzą bez zmiany wersji, więc Twój kod powinien ignorować pola, których nie zna.
Idempotencja #
Każdy POST może nieść nagłówek Idempotency-Key (1 do 255 znaków, np. UUID). Powtórzone zapytanie z tym samym kluczem i tą samą treścią zwraca zapisaną odpowiedź (nagłówek Idempotent-Replayed: true, X-Original-Request-Id pierwszego zapytania) i niczego nie wykonuje drugi raz. Ten sam klucz z inną treścią albo inną ścieżką to 409 klucz_idempotencji_uzyty. Klucz jest ważny 24 godziny, w zakresie sklepu i trybu (test albo live). Dwa identyczne zapytania naraz: drugie czeka na pierwsze.
Limit zapytań #
120 zapytań na minutę na klucz. Nagłówki X-RateLimit-Limit i X-RateLimit-Remaining w każdej odpowiedzi; po przekroczeniu 429 limit_zapytan z nagłówkiem Retry-After (sekundy).
Błędy #
Jeden obiekt błędu dla całego API (schemat Blad): typ grupuje kody (dane_nieprawidlowe, uwierzytelnienie, nie_znaleziono, plan, operator, konflikt, limit, zadanie_nieprawidlowe, blad_serwera), kod jest konkretny i stabilny, opis po polsku, pole wskazuje pierwsze złe pole, pola zawiera komunikaty dla wszystkich pól, dokumentacja prowadzi do opisu kodu, zadanie_id to identyfikator zapytania. Pełna lista kodów w x-kody-bledow.
Pełna lista kodów błędów z opisem, co zrobić.
Listy #
Listy mają obiekt: "lista", dane (najnowsze pierwsze) i ma_wiecej. Stronicowanie kursorem: limit (1 do 100), po=<id> daje obiekty starsze od podanego (następna strona), przed=<id> nowsze (poprzednia strona). Bez kursora działa stronicowanie numerem strona (dodatkowo strona, stron, razem).
Piaskownica #
Klucz testowy działa od założenia konta, pieniądze nie płyną, a ekran płatności prowadzi do banku testowego. Dane testowe są w x-piaskownica: kod BLIK 777777 zatwierdza płatność, 111111 kończy się odmową banku; dla karty i przelewu klient wybiera „Zatwierdź płatność” albo „Odrzuć w banku”. Do testów automatycznych służy POST /v1/platnosci/{id}/symulacja, które ustawia wynik bez ekranu i wysyła ten sam webhook co prawdziwa płatność.
curl "https://placenie.pl/api/v1/platnosci?limit=1" \
-H "Authorization: Bearer plc_test_..."
HTTP/1.1 201 Created
Content-Type: application/json
X-Request-Id: req_k3j2h1g0f9e8d7c6b5a4z3y2
Placenie-Version: 2026-10-03
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
{
"blad": {
"typ": "uwierzytelnienie",
"kod": "klucz_nieprawidlowy",
"opis": "Brak albo nieprawidłowy klucz API.",
"dokumentacja": "https://placenie.pl/docs/bledy#klucz_nieprawidlowy",
"zadanie_id": "req_k3j2h1g0f9e8d7c6b5a4z3y2"
}
}
# pierwsza strona
GET /v1/platnosci?limit=50
# nastepna strona: id ostatniego obiektu z poprzedniej
GET /v1/platnosci?limit=50&po=tr_8h2k1j0f9e8d7c6b5a4z
# poprzednia strona: id pierwszego obiektu z biezacej
GET /v1/platnosci?limit=50&przed=tr_3c9d2e1f0a7b6c5d4e3f
Płatności
Obiekt platnosc: utworzenie, status, zmiana opisu i metadanych, zwrot, lista, symulacja w piaskownicy.
Utwórz płatność #
POST /v1/platnosci
Tworzy płatność i zwraca adres_platnosci, na który kierujesz klienta. Po zapłacie klient wraca na adres_powrotu z parametrem placenie_id=<id>, a Ty dostajesz webhook platnosc.oplacona. Status zawsze sprawdzaj po swojej stronie (webhook albo GET /v1/platnosci/{id}), nie po samym powrocie klienta.
Ten sam numer_zamowienia z tą samą kwotą i walutą zwraca istniejącą płatność (200 zamiast 201). Ten sam numer z inną kwotą to 409 numer_zamowienia_zajety. Do ponawiania zapytań użyj nagłówka Idempotency-Key.
Nagłówki
- Idempotency-Key string
-
Klucz idempotencji (1 do 255 znaków drukowalnych, np. UUID). Patrz „Idempotencja” we wstępie.
od
1do255Przykład:
0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c - Placenie-Version string (enum)
-
Wersja API (data), którą ma obsłużyć zapytanie. Domyślnie najnowsza.
Wartości:
2026-10-012026-10-03
Treść żądania (JSON)
- kwota integer wymagane
-
Kwota w groszach (najmniejszej jednostce waluty). Od 1,00 do 999 999,99.
od
100do99999999Przykład:
12900 -
waluta
Waluta
domyślnie
PLN -
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - numer_zamowienia string, nullable
-
Twój numer zamówienia. Ten sam numer z tą samą kwotą i walutą zwraca istniejącą płatność zamiast tworzyć drugą.
do
120Przykład:
ZAM-2026-001 - opis string, nullable
-
Opis widoczny dla klienta na ekranie płatności i w panelu.
do
255 - email_klienta string (email), nullable
-
Adres klienta; może trafić do operatora jako dane płatnika.
do
160 - adres_powrotu string (uri), nullable
-
Dokąd wraca klient po płatności. Dopisujemy
?placenie_id=<id>. Powrót nie jest potwierdzeniem zapłaty; potwierdzeniem jest webhook alboGET /v1/platnosci/{id}.do
500 - metadane Metadane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" }
Odpowiedzi
- 200
-
Istniejąca płatność o tym samym
numer_zamowienia, kwocie i walucie (albo powtórka zIdempotency-Key). Treść: Platnosc Nagłówki:Idempotent-Replayed - 201
-
Płatność utworzona.
Treść: Platnosc
Nagłówki:
X-Request-Id,Placenie-Version - 400
-
Zapytanie nie do wykonania w tym kontekście (
klucz_idempotencji_nieprawidlowy,wersja_nieznana,tylko_piaskownica). Treść: Blad Nagłówki:X-Request-Id - 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 402
-
Plan albo stan konta nie pozwala (
plan_nieoplacony,funkcja_poza_planem,sklep_poza_planem,limit_demo). Treść: Blad - 409
-
Konflikt ze stanem (
numer_zamowienia_zajety,operator_niepodlaczony,klucz_idempotencji_uzyty,klucz_idempotencji_w_toku,stan_nieprawidlowy,webhook_nieustawiony). Treść: Blad - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci" \
-H "Authorization: Bearer plc_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c" \
-d '{
"kwota": 12900,
"waluta": "PLN",
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
}
}'
$ch = curl_init('https://placenie.pl/api/v1/platnosci');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Content-Type: application/json',
'Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
],
CURLOPT_POSTFIELDS => json_encode([
'kwota' => 12900,
'waluta' => 'PLN',
'numer_zamowienia' => 'ZAM-2026-001',
'opis' => 'Zamówienie ZAM-2026-001',
'email_klienta' => '[email protected]',
'adres_powrotu' => 'https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy',
'metadane' => [
'koszyk' => 'c_8812',
'klient_crm' => '4471',
],
]),
CURLOPT_RETURNTRANSFER => true,
]);
$platnosc = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosc['blad']['kod'].': '.$platnosc['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Content-Type': 'application/json',
'Idempotency-Key': '0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
},
body: JSON.stringify({
kwota: 12900,
waluta: 'PLN',
numer_zamowienia: 'ZAM-2026-001',
opis: 'Zamówienie ZAM-2026-001',
email_klienta: '[email protected]',
adres_powrotu: 'https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy',
metadane: {
koszyk: 'c_8812',
klient_crm: '4471',
},
}),
});
const platnosc = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosc.blad.kod}: ${platnosc.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci",
headers={"Authorization": "Bearer plc_test_...", "Idempotency-Key": "0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c"},
json={
"kwota": 12900,
"waluta": "PLN",
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471",
},
},
)
platnosc = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosc['blad']['kod']}: {platnosc['blad']['opis']}")
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "nowa",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 0,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": null,
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": null,
"zwroty": []
}
Lista płatności #
GET /v1/platnosci
Płatności klucza (tylko jego tryb), najnowsze pierwsze. Filtry łączą się ze sobą i z kursorami.
Parametry zapytania
- status StatusPlatnosci
-
Tylko płatności w tym statusie.
Wartości:
nowaoczekujeoplaconaodrzuconazwrocona - metoda Metoda
-
Tylko płatności tą metodą.
Wartości:
blikcardtransfer - numer_zamowienia string
-
Dokładny numer zamówienia.
do
120 - od string (date)
-
Utworzone od tego dnia włącznie (RRRR-MM-DD).
Przykład:
2026-10-01 - do string (date)
-
Utworzone do tego dnia włącznie (RRRR-MM-DD).
Przykład:
2026-10-31 -
limit
integer
domyślnie
100 -
Liczba obiektów na stronie, 1 do 100. Domyślnie 100.
od
1do100 - po string
-
Kursor „następna strona”: identyfikator ostatniego obiektu z poprzedniej strony; zwraca obiekty od niego starsze. Nie łączy się z
przed. - przed string
-
Kursor „poprzednia strona”: identyfikator pierwszego obiektu z bieżącej strony; zwraca obiekty od niego nowsze. Nie łączy się z
po. -
strona
integer
domyślnie
1 -
Numer strony (stronicowanie sprzed kursorów). Ignorowany, gdy podano
poalboprzed.od
1
Odpowiedzi
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/platnosci?status=oplacona&metoda=blik" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/platnosci?status=oplacona&metoda=blik');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$lista = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($lista['blad']['kod'].': '.$lista['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci?status=oplacona&metoda=blik', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const lista = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${lista.blad.kod}: ${lista.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/platnosci?status=oplacona&metoda=blik",
headers={"Authorization": "Bearer plc_test_..."},
)
lista = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{lista['blad']['kod']}: {lista['blad']['opis']}")
{
"obiekt": "lista",
"adres": "/v1/platnosci",
"dane": [
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
],
"ma_wiecej": true
}
Pobierz płatność #
GET /v1/platnosci/{id}
Aktualny stan płatności razem z listą zwrotów. Dla płatności produkcyjnej w statusie oczekuje pytamy operatora o stan na bieżąco, więc odpowiedź jest aktualna nawet, gdy webhook jeszcze nie dotarł.
Parametry ścieżki
- id string wymagane
-
Identyfikator płatności (
tr_i 20 znaków).wzór
^tr_[a-z0-9]{20}$Przykład:
tr_8h2k1j0f9e8d7c6b5a4z
Odpowiedzi
- 200
- Płatność. Treść: Platnosc
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$platnosc = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosc['blad']['kod'].': '.$platnosc['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const platnosc = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosc.blad.kod}: ${platnosc.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z",
headers={"Authorization": "Bearer plc_test_..."},
)
platnosc = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosc['blad']['kod']}: {platnosc['blad']['opis']}")
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
Zmień opis albo metadane #
POST /v1/platnosci/{id}
Zmienia pola, które nie dotyczą pieniędzy: opis i metadane. Metadane są scalane: podane klucze nadpisują istniejące, wartość null usuwa klucz, pozostałe klucze zostają. Kwoty, waluty ani statusu nie da się zmienić.
Parametry ścieżki
- id string wymagane
-
Identyfikator płatności (
tr_i 20 znaków).wzór
^tr_[a-z0-9]{20}$Przykład:
tr_8h2k1j0f9e8d7c6b5a4z
Nagłówki
- Idempotency-Key string
-
Klucz idempotencji (1 do 255 znaków drukowalnych, np. UUID). Patrz „Idempotencja” we wstępie.
od
1do255Przykład:
0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c
Treść żądania (JSON)
- opis string, nullable
-
do
255 - metadane object, nullable
-
Scalane z istniejącymi;
nullprzy kluczu usuwa ten klucz.
Odpowiedzi
- 200
- Płatność po zmianie. Treść: Platnosc
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z" \
-H "Authorization: Bearer plc_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c" \
-d '{
"opis": "Zamówienie ZAM-2026-001, wysłane",
"metadane": {
"koszyk": null,
"numer_listu": "00340434292135100186"
}
}'
$ch = curl_init('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Content-Type: application/json',
'Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
],
CURLOPT_POSTFIELDS => json_encode([
'opis' => 'Zamówienie ZAM-2026-001, wysłane',
'metadane' => [
'koszyk' => null,
'numer_listu' => '00340434292135100186',
],
]),
CURLOPT_RETURNTRANSFER => true,
]);
$platnosc = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosc['blad']['kod'].': '.$platnosc['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Content-Type': 'application/json',
'Idempotency-Key': '0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
},
body: JSON.stringify({
opis: 'Zamówienie ZAM-2026-001, wysłane',
metadane: {
koszyk: null,
numer_listu: '00340434292135100186',
},
}),
});
const platnosc = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosc.blad.kod}: ${platnosc.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z",
headers={"Authorization": "Bearer plc_test_...", "Idempotency-Key": "0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c"},
json={
"opis": "Zamówienie ZAM-2026-001, wysłane",
"metadane": {
"koszyk": None,
"numer_listu": "00340434292135100186",
},
},
)
platnosc = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosc['blad']['kod']}: {platnosc['blad']['opis']}")
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
Zwróć płatność #
POST /v1/platnosci/{id}/zwroty
Zwrot pełny (bez kwota) albo częściowy, tą samą drogą, którą przyszła płatność. Zwrot jest możliwy tylko dla płatności oplacona, do wysokości do_zwrotu. Kilka zwrotów częściowych może razem dojść do pełnej kwoty; po pełnym zwrocie status płatności to zwrocona. W produkcji zwrot może dostać status zlecony (czeka u operatora), a po jego rozstrzygnięciu dostaniesz platnosc.zwrot_odrzucony, jeśli operator odmówił.
Odpowiedź to płatność z pełną listą zwroty; ostatni element to nowy zwrot. Zdarzenie platnosc.zwrot niesie go w polu zwrot.
Parametry ścieżki
- id string wymagane
-
Identyfikator płatności (
tr_i 20 znaków).wzór
^tr_[a-z0-9]{20}$Przykład:
tr_8h2k1j0f9e8d7c6b5a4z
Nagłówki
- Idempotency-Key string
-
Klucz idempotencji (1 do 255 znaków drukowalnych, np. UUID). Patrz „Idempotencja” we wstępie.
od
1do255Przykład:
0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c
Treść żądania (JSON, opcjonalna)
- kwota integer
-
Kwota zwrotu w groszach. Bez tego pola zwrot całej kwoty pozostałej do zwrotu.
od
1Przykład:
2900
Odpowiedzi
- 201
- Zwrot przyjęty. Płatność z listą zwrotów. Treść: Platnosc
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 422
-
Zwrot odrzucony (
zwrot_odrzucony, np. płatność nieopłacona albo kwota ponaddo_zwrotu) albo złe pola. Treść: Blad - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/zwroty" \
-H "Authorization: Bearer plc_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c" \
-d '{
"kwota": 2900
}'
$ch = curl_init('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/zwroty');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Content-Type: application/json',
'Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
],
CURLOPT_POSTFIELDS => json_encode([
'kwota' => 2900,
]),
CURLOPT_RETURNTRANSFER => true,
]);
$platnosc = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosc['blad']['kod'].': '.$platnosc['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/zwroty', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Content-Type': 'application/json',
'Idempotency-Key': '0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
},
body: JSON.stringify({
kwota: 2900,
}),
});
const platnosc = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosc.blad.kod}: ${platnosc.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/zwroty",
headers={"Authorization": "Bearer plc_test_...", "Idempotency-Key": "0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c"},
json={
"kwota": 2900,
},
)
platnosc = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosc['blad']['kod']}: {platnosc['blad']['opis']}")
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 2900,
"do_zwrotu": 10000,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": [
{
"obiekt": "zwrot",
"id": "zw_9f8e7d6c5b4a3z2y1x0w",
"platnosc": "tr_8h2k1j0f9e8d7c6b5a4z",
"kwota": 2900,
"waluta": "PLN",
"status": "wykonany",
"zrodlo": "api",
"utworzony": "2026-10-03T12:30:00+00:00"
}
]
}
[]
Symuluj wynik (piaskownica) #
POST /v1/platnosci/{id}/symulacja
Tylko klucz testowy. Ustawia wynik płatności bez przechodzenia ekranu testowego, tą samą drogą co bank testowy: powstaje zdarzenie i idzie webhook. Działa dla płatności nowa albo odrzucona; dla innych 409 stan_nieprawidlowy. Kluczem produkcyjnym: 400 tylko_piaskownica.
Parametry ścieżki
- id string wymagane
-
Identyfikator płatności (
tr_i 20 znaków).wzór
^tr_[a-z0-9]{20}$Przykład:
tr_8h2k1j0f9e8d7c6b5a4z
Treść żądania (JSON)
- wynik string (enum) wymagane
-
Wynik, który ma dostać płatność.
Wartości:
oplaconaodrzucona - metoda Metoda
-
Metoda zapisana przy płatności. Domyślnie wybrana wcześniej na ekranie albo
blik.Wartości:
blikcardtransfer
Odpowiedzi
- 200
- Płatność po symulacji. Treść: Platnosc
- 400
-
Zapytanie nie do wykonania w tym kontekście (
klucz_idempotencji_nieprawidlowy,wersja_nieznana,tylko_piaskownica). Treść: Blad Nagłówki:X-Request-Id - 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 409
-
Konflikt ze stanem (
numer_zamowienia_zajety,operator_niepodlaczony,klucz_idempotencji_uzyty,klucz_idempotencji_w_toku,stan_nieprawidlowy,webhook_nieustawiony). Treść: Blad - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/symulacja" \
-H "Authorization: Bearer plc_test_..." \
-H "Content-Type: application/json" \
-d '{
"wynik": "oplacona",
"metoda": "blik"
}'
$ch = curl_init('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/symulacja');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'wynik' => 'oplacona',
'metoda' => 'blik',
]),
CURLOPT_RETURNTRANSFER => true,
]);
$platnosc = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosc['blad']['kod'].': '.$platnosc['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/symulacja', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
wynik: 'oplacona',
metoda: 'blik',
}),
});
const platnosc = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosc.blad.kod}: ${platnosc.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci/tr_8h2k1j0f9e8d7c6b5a4z/symulacja",
headers={"Authorization": "Bearer plc_test_..."},
json={
"wynik": "oplacona",
"metoda": "blik",
},
)
platnosc = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosc['blad']['kod']}: {platnosc['blad']['opis']}")
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
{
"wynik": "odrzucona"
}
Płatności cykliczne
Obiekt platnosc_cykliczna (plan Sklep i wyższe): zgoda klienta, obciążenia z harmonogramu, ponowienia po odmowie, rezygnacja.
Utwórz płatność cykliczną #
POST /v1/platnosci-cykliczne
Plan Sklep i wyższe. Tworzy zgodę w stanie oczekuje i zwraca adres_zgody: wyślij tam klienta. Klient widzi kwotę, okres i sposób rezygnacji, zgadza się i płaci pierwszy raz kartą (3-D Secure, dane karty wpisuje w formularz operatora). Kolejne obciążenia idą z harmonogramu co okres, bez udziału klienta; każde to zwykła platnosc z polem platnosc_cykliczna. Kilka dni przed obciążeniem klient dostaje wiadomość. Po odmowie banku ponawiamy po 1, 3 i 5 dniach, potem zgoda jest wstrzymana, dopóki klient nie poda nowej karty pod tym samym adres_zgody. Kluczem produkcyjnym wymaga podłączonego operatora (409 operator_niepodlaczony). Plan bez tej funkcji: 402 funkcja_poza_planem.
Nagłówki
- Idempotency-Key string
-
Klucz idempotencji (1 do 255 znaków drukowalnych, np. UUID). Patrz „Idempotencja” we wstępie.
od
1do255Przykład:
0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c
Treść żądania (JSON)
- kwota integer wymagane
-
Kwota każdego obciążenia w groszach.
od
100do99999999 - waluta Waluta
-
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - okres string (enum) wymagane
-
Wartości:
tydzienmiesiackwartalrok - opis string wymagane
-
Za co płaci klient; widzi to na ekranie zgody i w wiadomościach.
do
255 - email_klienta string (email) wymagane
-
Na ten adres idą zapowiedzi obciążeń i link do rezygnacji.
do
160 - numer_klienta string, nullable
-
do
120 - adres_powrotu string (uri), nullable
-
do
500 - metadane Metadane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" }
Odpowiedzi
- 201
- Płatność cykliczna czeka na zgodę klienta. Treść: PlatnoscCykliczna
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 402
-
Plan albo stan konta nie pozwala (
plan_nieoplacony,funkcja_poza_planem,sklep_poza_planem,limit_demo). Treść: Blad - 409
-
Konflikt ze stanem (
numer_zamowienia_zajety,operator_niepodlaczony,klucz_idempotencji_uzyty,klucz_idempotencji_w_toku,stan_nieprawidlowy,webhook_nieustawiony). Treść: Blad - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci-cykliczne" \
-H "Authorization: Bearer plc_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c" \
-d '{
"kwota": 4900,
"okres": "miesiac",
"opis": "Abonament Premium",
"email_klienta": "[email protected]",
"numer_klienta": "K-1024"
}'
$ch = curl_init('https://placenie.pl/api/v1/platnosci-cykliczne');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Content-Type: application/json',
'Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
],
CURLOPT_POSTFIELDS => json_encode([
'kwota' => 4900,
'okres' => 'miesiac',
'opis' => 'Abonament Premium',
'email_klienta' => '[email protected]',
'numer_klienta' => 'K-1024',
]),
CURLOPT_RETURNTRANSFER => true,
]);
$platnosccykliczna = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosccykliczna['blad']['kod'].': '.$platnosccykliczna['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci-cykliczne', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Content-Type': 'application/json',
'Idempotency-Key': '0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
},
body: JSON.stringify({
kwota: 4900,
okres: 'miesiac',
opis: 'Abonament Premium',
email_klienta: '[email protected]',
numer_klienta: 'K-1024',
}),
});
const platnosccykliczna = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosccykliczna.blad.kod}: ${platnosccykliczna.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci-cykliczne",
headers={"Authorization": "Bearer plc_test_...", "Idempotency-Key": "0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c"},
json={
"kwota": 4900,
"okres": "miesiac",
"opis": "Abonament Premium",
"email_klienta": "[email protected]",
"numer_klienta": "K-1024",
},
)
platnosccykliczna = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosccykliczna['blad']['kod']}: {platnosccykliczna['blad']['opis']}")
Lista płatności cyklicznych #
GET /v1/platnosci-cykliczne
Najnowsze pierwsze, z filtrem status. Stronicowanie jak w liście płatności.
Parametry zapytania
-
limit
integer
domyślnie
100 -
Liczba obiektów na stronie, 1 do 100. Domyślnie 100.
od
1do100 - po string
-
Kursor „następna strona”: identyfikator ostatniego obiektu z poprzedniej strony; zwraca obiekty od niego starsze. Nie łączy się z
przed. - przed string
-
Kursor „poprzednia strona”: identyfikator pierwszego obiektu z bieżącej strony; zwraca obiekty od niego nowsze. Nie łączy się z
po. -
strona
integer
domyślnie
1 -
Numer strony (stronicowanie sprzed kursorów). Ignorowany, gdy podano
poalboprzed.od
1 - status StatusPlatnosciCyklicznej
-
Wartości:
oczekujeaktywnaponawianawstrzymanaanulowana
Odpowiedzi
- 200
-
Lista obiektów
platnosc_cykliczna. Treść: Lista - 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/platnosci-cykliczne?limit=20&status=ponawiana" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/platnosci-cykliczne?limit=20&status=ponawiana');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$lista = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($lista['blad']['kod'].': '.$lista['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci-cykliczne?limit=20&status=ponawiana', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const lista = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${lista.blad.kod}: ${lista.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/platnosci-cykliczne?limit=20&status=ponawiana",
headers={"Authorization": "Bearer plc_test_..."},
)
lista = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{lista['blad']['kod']}: {lista['blad']['opis']}")
Pobierz płatność cykliczną #
GET /v1/platnosci-cykliczne/{id}
Stan zgody, numer ostatniego opłaconego okresu (cykl), termin następnego obciążenia i liczba prób po odmowie.
Parametry ścieżki
- id string wymagane
-
wzór
^cy_[a-z0-9]{20}$
Odpowiedzi
- 200
- Płatność cykliczna. Treść: PlatnoscCykliczna
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/platnosci-cykliczne/id" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/platnosci-cykliczne/id');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$platnosccykliczna = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosccykliczna['blad']['kod'].': '.$platnosccykliczna['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci-cykliczne/id', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const platnosccykliczna = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosccykliczna.blad.kod}: ${platnosccykliczna.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/platnosci-cykliczne/id",
headers={"Authorization": "Bearer plc_test_..."},
)
platnosccykliczna = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosccykliczna['blad']['kod']}: {platnosccykliczna['blad']['opis']}")
Anuluj płatność cykliczną #
POST /v1/platnosci-cykliczne/{id}/anuluj
Harmonogram staje od razu, kolejnych obciążeń nie będzie. Ponowne anulowanie niczego nie zmienia. Idzie zdarzenie platnosc_cykliczna.anulowana.
Parametry ścieżki
- id string wymagane
-
wzór
^cy_[a-z0-9]{20}$
Nagłówki
- Idempotency-Key string
-
Klucz idempotencji (1 do 255 znaków drukowalnych, np. UUID). Patrz „Idempotencja” we wstępie.
od
1do255Przykład:
0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c
Odpowiedzi
- 200
- Płatność cykliczna po anulowaniu. Treść: PlatnoscCykliczna
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci-cykliczne/id/anuluj" \
-H "Authorization: Bearer plc_test_..." \
-H "Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c" \
-d ''
$ch = curl_init('https://placenie.pl/api/v1/platnosci-cykliczne/id/anuluj');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
'Idempotency-Key: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
],
CURLOPT_RETURNTRANSFER => true,
]);
$platnosccykliczna = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosccykliczna['blad']['kod'].': '.$platnosccykliczna['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci-cykliczne/id/anuluj', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
'Idempotency-Key': '0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c',
},
});
const platnosccykliczna = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosccykliczna.blad.kod}: ${platnosccykliczna.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci-cykliczne/id/anuluj",
headers={"Authorization": "Bearer plc_test_...", "Idempotency-Key": "0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c"},
)
platnosccykliczna = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosccykliczna['blad']['kod']}: {platnosccykliczna['blad']['opis']}")
Symuluj kolejne obciążenie (piaskownica) #
POST /v1/platnosci-cykliczne/{id}/symulacja
Tylko klucz testowy. Obciąża następny okres od razu, z wynikiem oplacona albo odrzucona, tą samą drogą co harmonogram: powstają zdarzenia i idą webhooki odnowienia, odmowy albo wstrzymania. Działa dla zgody aktywna albo ponawiana.
Parametry ścieżki
- id string wymagane
-
wzór
^cy_[a-z0-9]{20}$
Treść żądania (JSON)
- wynik string (enum) wymagane
-
Wartości:
oplaconaodrzucona
Odpowiedzi
- 200
- Płatność cykliczna po obciążeniu. Treść: PlatnoscCykliczna
- 400
-
Zapytanie nie do wykonania w tym kontekście (
klucz_idempotencji_nieprawidlowy,wersja_nieznana,tylko_piaskownica). Treść: Blad Nagłówki:X-Request-Id - 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 409
-
Konflikt ze stanem (
numer_zamowienia_zajety,operator_niepodlaczony,klucz_idempotencji_uzyty,klucz_idempotencji_w_toku,stan_nieprawidlowy,webhook_nieustawiony). Treść: Blad - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/platnosci-cykliczne/id/symulacja" \
-H "Authorization: Bearer plc_test_..." \
-d ''
$ch = curl_init('https://placenie.pl/api/v1/platnosci-cykliczne/id/symulacja');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$platnosccykliczna = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($platnosccykliczna['blad']['kod'].': '.$platnosccykliczna['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/platnosci-cykliczne/id/symulacja', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const platnosccykliczna = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${platnosccykliczna.blad.kod}: ${platnosccykliczna.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/platnosci-cykliczne/id/symulacja",
headers={"Authorization": "Bearer plc_test_..."},
)
platnosccykliczna = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{platnosccykliczna['blad']['kod']}: {platnosccykliczna['blad']['opis']}")
Zdarzenia
Obiekt zdarzenie: to samo, co idzie w webhooku, dostępne zapytaniem; ponowna dostawa webhooka.
Lista zdarzeń #
GET /v1/zdarzenia
Zdarzenia klucza (tylko jego tryb), najnowsze pierwsze. Każda zmiana stanu płatności zapisuje zdarzenie, także gdy sklep nie ma webhooka. Treść zdarzenia to dokładnie to, co idzie w webhooku, plus pole webhook ze stanem ostatniej dostawy (albo null, gdy adresu webhooka nie ma).
Parametry zapytania
- typ TypZdarzenia
-
Tylko zdarzenia tego typu.
Wartości:
platnosc.oczekujeplatnosc.oplaconaplatnosc.odrzuconaplatnosc.zwrotplatnosc.zwrot_odrzuconyplatnosc_cykliczna.aktywnaplatnosc_cykliczna.odnowionaplatnosc_cykliczna.odmowaplatnosc_cykliczna.wstrzymanaplatnosc_cykliczna.anulowana - platnosc string
-
Tylko zdarzenia tej płatności (
tr_...).Przykład:
tr_8h2k1j0f9e8d7c6b5a4z - od string (date)
- do string (date)
-
limit
integer
domyślnie
100 -
Liczba obiektów na stronie, 1 do 100. Domyślnie 100.
od
1do100 - po string
-
Kursor „następna strona”: identyfikator ostatniego obiektu z poprzedniej strony; zwraca obiekty od niego starsze. Nie łączy się z
przed. - przed string
-
Kursor „poprzednia strona”: identyfikator pierwszego obiektu z bieżącej strony; zwraca obiekty od niego nowsze. Nie łączy się z
po. -
strona
integer
domyślnie
1 -
Numer strony (stronicowanie sprzed kursorów). Ignorowany, gdy podano
poalboprzed.od
1
Odpowiedzi
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 422
-
Złe pola (
dane_nieprawidlowe,kursor_nieprawidlowy,waluta_poza_planem,zwrot_odrzucony). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/zdarzenia?typ=platnosc.oczekuje&limit=20" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/zdarzenia?typ=platnosc.oczekuje&limit=20');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$lista = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($lista['blad']['kod'].': '.$lista['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/zdarzenia?typ=platnosc.oczekuje&limit=20', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const lista = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${lista.blad.kod}: ${lista.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/zdarzenia?typ=platnosc.oczekuje&limit=20",
headers={"Authorization": "Bearer plc_test_..."},
)
lista = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{lista['blad']['kod']}: {lista['blad']['opis']}")
{
"obiekt": "lista",
"adres": "/v1/zdarzenia",
"dane": [
{
"obiekt": "zdarzenie",
"id": "evt_0a1b2c3d4e5f6g7h8i9j",
"typ": "platnosc.oplacona",
"tryb": "test",
"utworzone": "2026-10-03T10:01:12+00:00",
"transakcja": {
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
}
],
"ma_wiecej": false
}
Pobierz zdarzenie #
GET /v1/zdarzenia/{id}
Jedno zdarzenie. Przydatne, gdy odbiornik webhooka chce potwierdzić treść u źródła zamiast ufać samemu żądaniu.
Parametry ścieżki
- id string wymagane
-
Identyfikator zdarzenia (
evt_i 20 znaków).wzór
^evt_[a-z0-9]{20}$Przykład:
evt_0a1b2c3d4e5f6g7h8i9j
Odpowiedzi
- 200
- Zdarzenie. Treść: Zdarzenie
- 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl "https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j" \
-H "Authorization: Bearer plc_test_..."
$ch = curl_init('https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$zdarzenie = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($zdarzenie['blad']['kod'].': '.$zdarzenie['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j', {
method: 'GET',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const zdarzenie = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${zdarzenie.blad.kod}: ${zdarzenie.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j",
headers={"Authorization": "Bearer plc_test_..."},
)
zdarzenie = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{zdarzenie['blad']['kod']}: {zdarzenie['blad']['opis']}")
{
"obiekt": "zdarzenie",
"id": "evt_0a1b2c3d4e5f6g7h8i9j",
"typ": "platnosc.oplacona",
"tryb": "test",
"utworzone": "2026-10-03T10:01:12+00:00",
"transakcja": {
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
}
Ponów webhook zdarzenia #
POST /v1/zdarzenia/{id}/ponow
Wysyła webhook tego zdarzenia jeszcze raz (np. po naprawie odbiornika w sklepie). Nowa dostawa z nowym podpisem, ta sama treść i ten sam Placenie-Event-Id, więc odbiornik powinien być idempotentny po identyfikatorze zdarzenia. Bez adresu webhooka w panelu: 409 webhook_nieustawiony.
Parametry ścieżki
- id string wymagane
-
Identyfikator zdarzenia (
evt_i 20 znaków).wzór
^evt_[a-z0-9]{20}$Przykład:
evt_0a1b2c3d4e5f6g7h8i9j
Odpowiedzi
- 202
-
Dostawa wykonana albo zaplanowana do ponowień. Zdarzenie ze stanem dostawy w polu
webhook. Treść: Zdarzenie - 401
-
Brak albo nieprawidłowy klucz API (
klucz_nieprawidlowy). Treść: Blad Nagłówki:X-Request-Id - 404
-
Nie ma takiego obiektu dla tego klucza (
nie_znaleziono) albo takiego adresu (trasa_nieznana). Treść: Blad Nagłówki:X-Request-Id - 409
-
Konflikt ze stanem (
numer_zamowienia_zajety,operator_niepodlaczony,klucz_idempotencji_uzyty,klucz_idempotencji_w_toku,stan_nieprawidlowy,webhook_nieustawiony). Treść: Blad - 429
-
Przekroczony limit zapytań (
limit_zapytan). Ponów po czasie zRetry-After. Treść: Blad Nagłówki:Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining
curl -X POST "https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j/ponow" \
-H "Authorization: Bearer plc_test_..." \
-d ''
$ch = curl_init('https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j/ponow');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer plc_test_...',
],
CURLOPT_RETURNTRANSFER => true,
]);
$zdarzenie = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($zdarzenie['blad']['kod'].': '.$zdarzenie['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j/ponow', {
method: 'POST',
headers: {
Authorization: 'Bearer plc_test_...',
},
});
const zdarzenie = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${zdarzenie.blad.kod}: ${zdarzenie.blad.opis}`);
}
import requests
odpowiedz = requests.post(
"https://placenie.pl/api/v1/zdarzenia/evt_0a1b2c3d4e5f6g7h8i9j/ponow",
headers={"Authorization": "Bearer plc_test_..."},
)
zdarzenie = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{zdarzenie['blad']['kod']}: {zdarzenie['blad']['opis']}")
{
"obiekt": "zdarzenie",
"id": "evt_0a1b2c3d4e5f6g7h8i9j",
"typ": "platnosc.oplacona",
"tryb": "test",
"utworzone": "2026-10-03T10:01:12+00:00",
"transakcja": {
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
}
Specyfikacja
Ta specyfikacja w JSON, bez klucza.
Ta specyfikacja (OpenAPI 3.1, JSON) #
GET /v1/openapi.json bez klucza
Aktualna specyfikacja całego API, bez uwierzytelniania. Źródło w repozytorium to docs/openapi.yaml.
Odpowiedzi
- 200
- Dokument OpenAPI 3.1.
curl "https://placenie.pl/api/v1/openapi.json"
$ch = curl_init('https://placenie.pl/api/v1/openapi.json');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
],
CURLOPT_RETURNTRANSFER => true,
]);
$odpowiedz = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException($odpowiedz['blad']['kod'].': '.$odpowiedz['blad']['opis']);
}
const odpowiedz = await fetch('https://placenie.pl/api/v1/openapi.json', {
method: 'GET',
});
const odpowiedz = await odpowiedz.json();
if (!odpowiedz.ok) {
throw new Error(`${odpowiedz.blad.kod}: ${odpowiedz.blad.opis}`);
}
import requests
odpowiedz = requests.get(
"https://placenie.pl/api/v1/openapi.json",
)
odpowiedz = odpowiedz.json()
if not odpowiedz.ok:
raise RuntimeError(f"{odpowiedz['blad']['kod']}: {odpowiedz['blad']['opis']}")
Obiekty
Każdy obiekt ma pole obiekt z nazwą typu i identyfikator ze stałym prefiksem. Nowe pola dochodzą bez zmiany wersji, więc kod klienta powinien ignorować pola, których nie zna.
Metadane#
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
Pola
- {klucz} string
-
Dowolny klucz (do 40 znaków), wartość string.
do
500
{
"koszyk": "c_8812",
"klient_crm": "4471"
}
NowaPlatnosc#
Pola
- kwota integer wymagane
-
Kwota w groszach (najmniejszej jednostce waluty). Od 1,00 do 999 999,99.
od
100do99999999Przykład:
12900 -
waluta
Waluta
domyślnie
PLN -
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - numer_zamowienia string, nullable
-
Twój numer zamówienia. Ten sam numer z tą samą kwotą i walutą zwraca istniejącą płatność zamiast tworzyć drugą.
do
120Przykład:
ZAM-2026-001 - opis string, nullable
-
Opis widoczny dla klienta na ekranie płatności i w panelu.
do
255 - email_klienta string (email), nullable
-
Adres klienta; może trafić do operatora jako dane płatnika.
do
160 - adres_powrotu string (uri), nullable
-
Dokąd wraca klient po płatności. Dopisujemy
?placenie_id=<id>. Powrót nie jest potwierdzeniem zapłaty; potwierdzeniem jest webhook alboGET /v1/platnosci/{id}.do
500 - metadane Metadane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" }
ZmianaPlatnosci#
Pola
- opis string, nullable
-
do
255 - metadane object, nullable
-
Scalane z istniejącymi;
nullprzy kluczu usuwa ten klucz.
NowyZwrot#
Pola
- kwota integer
-
Kwota zwrotu w groszach. Bez tego pola zwrot całej kwoty pozostałej do zwrotu.
od
1Przykład:
2900
Zwrot#
Pola
- obiekt stała "zwrot" wymagane
- id string wymagane
-
wzór
^zw_[a-z0-9]{20}$Przykład:
zw_9f8e7d6c5b4a3z2y1x0w - platnosc string wymagane
-
Identyfikator płatności, której dotyczy zwrot.
- kwota integer wymagane
-
Kwota zwrotu w groszach.
- waluta Waluta wymagane
-
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - status StatusZwrotu wymagane
-
wykonanyzakończony,zleconyczeka u operatora (produkcja),odrzuconyoperator odmówił (kwota wróciła do puli).Wartości:
wykonanyzleconyodrzucony - zrodlo string (enum) wymagane
-
Skąd zlecono zwrot.
Wartości:
apipanel - utworzony string (date-time) wymagane
{
"obiekt": "zwrot",
"id": "zw_9f8e7d6c5b4a3z2y1x0w",
"platnosc": "tr_8h2k1j0f9e8d7c6b5a4z",
"kwota": 2900,
"waluta": "PLN",
"status": "wykonany",
"zrodlo": "api",
"utworzony": "2026-10-03T12:30:00+00:00"
}
Platnosc#
Płatność (transakcja). Ta sama postać w odpowiedziach API i w polu transakcja zdarzenia.
Pola
- obiekt stała "platnosc" wymagane
- id string wymagane
-
wzór
^tr_[a-z0-9]{20}$Przykład:
tr_8h2k1j0f9e8d7c6b5a4z - tryb Tryb wymagane
-
testto piaskownica (kluczplc_test_),liveto produkcja (kluczplc_live_).Wartości:
testlive - status StatusPlatnosci wymagane
-
nowa: utworzona, klient jeszcze nie zapłacił,oczekuje: klient poszedł do operatora, czekamy na wynik (produkcja),oplacona: pieniądze zaksięgowane; stan końcowy, z którego możliwy jest tylko zwrot,odrzucona: bank albo operator odmówił; klient może spróbować ponownie z tego samego adresu płatności,zwrocona: zwrócona w całości.
Wartości:
nowaoczekujeoplaconaodrzuconazwrocona - kwota integer wymagane
-
Kwota w groszach.
- waluta Waluta wymagane
-
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - zwrocono integer wymagane
-
Suma wykonanych i zleconych zwrotów w groszach.
- do_zwrotu integer wymagane
-
Ile jeszcze można zwrócić (0, gdy płatność nie jest
oplacona). - numer_zamowienia string, nullable
- opis string, nullable
- email_klienta string, nullable
- adres_powrotu string, nullable
- metoda Metoda, nullable
-
Metoda wybrana przez klienta;
null, dopóki nie wybrał.Wartości:
blikcardtransfer - platnosc_cykliczna string, nullable
-
Id płatności cyklicznej, gdy to jej obciążenie.
- okres_cykliczny integer, nullable
-
Numer okresu płatności cyklicznej.
- metadane Metadane wymagane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" } - adres_platnosci string (uri) wymagane
-
Ekran płatności dla klienta. Przekieruj go tam (albo otwórz w nowej karcie).
Przykład:
https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z - utworzona string (date-time) wymagane
- oplacona string (date-time), nullable
-
Czas zaksięgowania;
nullprzed zapłatą. - zwroty array<Zwrot> wymagane
-
Zwroty w kolejności zlecenia.
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
NowaPlatnoscCykliczna#
Pola
- kwota integer wymagane
-
Kwota każdego obciążenia w groszach.
od
100do99999999 - waluta Waluta
-
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - okres string (enum) wymagane
-
Wartości:
tydzienmiesiackwartalrok - opis string wymagane
-
Za co płaci klient; widzi to na ekranie zgody i w wiadomościach.
do
255 - email_klienta string (email) wymagane
-
Na ten adres idą zapowiedzi obciążeń i link do rezygnacji.
do
160 - numer_klienta string, nullable
-
do
120 - adres_powrotu string (uri), nullable
-
do
500 - metadane Metadane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" }
PlatnoscCykliczna#
Zgoda klienta na obciążenia według harmonogramu. Dane karty i token nigdy nie wychodzą.
Pola
- obiekt stała "platnosc_cykliczna" wymagane
- id string wymagane
-
wzór
^cy_[a-z0-9]{20}$ - tryb Tryb wymagane
-
testto piaskownica (kluczplc_test_),liveto produkcja (kluczplc_live_).Wartości:
testlive - status StatusPlatnosciCyklicznej wymagane
-
Wartości:
oczekujeaktywnaponawianawstrzymanaanulowana - kwota integer wymagane
- waluta Waluta wymagane
-
Kod ISO 4217.
PLNw każdym planie;EUR,USD,GBP,CZKw planie Skala i Enterprise.od
3do3Przykład:
PLN - okres string (enum) wymagane
-
Wartości:
tydzienmiesiackwartalrok - opis string wymagane
- email_klienta string wymagane
- numer_klienta string, nullable
- adres_powrotu string, nullable
- metoda string, nullable
- karta string, nullable
-
Zamaskowany numer karty od operatora.
- metadane Metadane
-
Dowolne pary klucz: wartość Twojego systemu (numer koszyka, id klienta w CRM). Najwyżej 50 kluczy, klucz do 40 znaków, wartość do 500 znaków. Liczby i wartości logiczne są zapisywane jako teksty. Nigdy nie pokazujemy ich kupującemu.
najwyżej
50Przykład:
{ "koszyk": "c_8812", "klient_crm": "4471" } - adres_zgody string (uri) wymagane
-
Ekran zgody dla klienta, także do podania nowej karty po odmowie.
- cykl integer wymagane
-
Numer ostatniego opłaconego okresu (0 przed pierwszą płatnością).
- nastepne_obciazenie string (date-time), nullable
- proby integer wymagane
-
Liczba odmów w bieżącym okresie.
- zgoda string (date-time), nullable
- anulowana string (date-time), nullable
- anulowana_przez string (enum), nullable
-
Wartości:
klientsklep - utworzona string (date-time) wymagane
Zdarzenie#
Zdarzenie (treść webhooka). Pole webhook jest tylko w odpowiedziach API, nie w samym webhooku.
Pola
- obiekt stała "zdarzenie" wymagane
- id string wymagane
-
wzór
^evt_[a-z0-9]{20}$Przykład:
evt_0a1b2c3d4e5f6g7h8i9j - typ TypZdarzenia wymagane
-
Wartości:
platnosc.oczekujeplatnosc.oplaconaplatnosc.odrzuconaplatnosc.zwrotplatnosc.zwrot_odrzuconyplatnosc_cykliczna.aktywnaplatnosc_cykliczna.odnowionaplatnosc_cykliczna.odmowaplatnosc_cykliczna.wstrzymanaplatnosc_cykliczna.anulowana - tryb Tryb wymagane
-
testto piaskownica (kluczplc_test_),liveto produkcja (kluczplc_live_).Wartości:
testlive - utworzone string (date-time) wymagane
- transakcja Platnosc wymagane
-
Płatność (transakcja). Ta sama postać w odpowiedziach API i w polu
transakcjazdarzenia. - zwrot Zwrot
-
Tylko przy
platnosc.zwrotiplatnosc.zwrot_odrzucony. - platnosc_cykliczna PlatnoscCykliczna
-
Tylko przy zdarzeniach
platnosc_cykliczna.*. - webhook object, nullable
-
Stan ostatniej dostawy webhooka tego zdarzenia;
null, gdy sklep nie ma adresu webhooka.- status string (enum)
-
Wartości:
czekadostarczonyporzucony - proby integer
- ostatni_kod integer, nullable
-
Kod HTTP ostatniej odpowiedzi odbiornika.
- ostatni_blad string, nullable
- nastepna_proba string (date-time), nullable
{
"obiekt": "zdarzenie",
"id": "evt_0a1b2c3d4e5f6g7h8i9j",
"typ": "platnosc.oplacona",
"tryb": "test",
"utworzone": "2026-10-03T10:01:12+00:00",
"transakcja": {
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/zamowienie/ZAM-2026-001/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812",
"klient_crm": "4471"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
}
Lista#
Pola
- obiekt stała "lista" wymagane
- adres string wymagane
-
Ścieżka listy, np.
/v1/platnosci. - dane array<object> wymagane
- ma_wiecej boolean wymagane
-
Czy są kolejne obiekty za tą stroną (starsze).
- strona integer
-
Tylko w stronicowaniu numerem strony.
- stron integer
-
Tylko w stronicowaniu numerem strony.
- razem integer
-
Tylko w stronicowaniu numerem strony.
{
"obiekt": "lista",
"adres": "/v1/platnosci",
"dane": [
{
"obiekt": "platnosc",
"id": "tr_8h2k1j0f9e8d7c6b5a4z",
"tryb": "test",
"status": "oplacona",
"kwota": 12900,
"waluta": "PLN",
"zwrocono": 0,
"do_zwrotu": 12900,
"numer_zamowienia": "ZAM-2026-001",
"opis": "Zamówienie ZAM-2026-001",
"email_klienta": "[email protected]",
"adres_powrotu": "https://twojsklep.pl/dziekujemy",
"metoda": "blik",
"metadane": {
"koszyk": "c_8812"
},
"adres_platnosci": "https://placenie.pl/zaplac/tr_8h2k1j0f9e8d7c6b5a4z",
"utworzona": "2026-10-03T10:00:00+00:00",
"oplacona": "2026-10-03T10:01:12+00:00",
"zwroty": []
}
],
"ma_wiecej": true
}
Blad#
Pola
- blad object wymagane
-
- typ string (enum) wymagane
-
Grupa błędu. Obsługuj typ, gdy nie potrzebujesz rozróżniać kodów.
Wartości:
dane_nieprawidloweuwierzytelnienienie_znalezionoplanoperatorkonfliktlimitzadanie_nieprawidloweblad_serwera - kod string wymagane
-
Stabilny kod błędu (lista w
x-kody-bledow). - opis string wymagane
-
Opis po polsku, do pokazania w logu albo operatorowi sklepu.
- pole string
-
Pierwsze pole z błędem (tylko przy błędach pól).
- pola object
-
Komunikaty dla wszystkich pól z błędami (tylko przy błędach pól).
- dokumentacja string (uri) wymagane
-
Opis kodu w dokumentacji.
- zadanie_id string wymagane
-
Identyfikator zapytania, ten sam co nagłówek
X-Request-Id. - szczegoly string
-
Tylko w środowisku deweloperskim przy błędzie serwera.
{
"blad": {
"typ": "dane_nieprawidlowe",
"kod": "dane_nieprawidlowe",
"opis": "Popraw pola zapytania.",
"pole": "kwota",
"pola": {
"kwota": [
"The kwota field must be at least 100."
]
},
"dokumentacja": "https://placenie.pl/docs/bledy#dane_nieprawidlowe",
"zadanie_id": "req_k3j2h1g0f9e8d7c6b5a4z3y2"
}
}
Typy proste
Wartości wyliczeniowe używane w polach obiektów i w filtrach list.
| Typ | Wartości | Opis |
|---|---|---|
| Tryb |
testlive
|
|
| Waluta | string | Kod ISO 4217. |
| Metoda |
blikcardtransfer
|
|
| StatusPlatnosci |
nowaoczekujeoplaconaodrzuconazwrocona
|
|
| StatusZwrotu |
wykonanyzleconyodrzucony
|
|
| TypZdarzenia |
platnosc.oczekujeplatnosc.oplaconaplatnosc.odrzuconaplatnosc.zwrotplatnosc.zwrot_odrzuconyplatnosc_cykliczna.aktywnaplatnosc_cykliczna.odnowionaplatnosc_cykliczna.odmowaplatnosc_cykliczna.wstrzymanaplatnosc_cykliczna.anulowana
|
|
| StatusPlatnosciCyklicznej |
oczekujeaktywnaponawianawstrzymanaanulowana
|
Webhooki
POST na adres webhooka z panelu (tylko https, publiczny host). Nagłówki: Placenie-Signature, Placenie-Event-Id, Placenie-Event-Type, User-Agent: Placenie-Webhook/1. Odpowiedz kodem 2xx w ciągu 8 sekund. Każda inna odpowiedź oznacza ponowienie po 1, 5, 15 i 60 minutach, potem po 3, 6 i 12 godzinach, potem dostawa jest porzucona (zdarzenie nadal można pobrać przez GET /v1/zdarzenia/{id} i ponowić przez POST /v1/zdarzenia/{id}/ponow). Kolejność dostaw nie jest gwarantowana: zawsze patrz na transakcja.status, nie na kolejność webhooków.
| Typ zdarzenia | Kiedy | Opis |
|---|---|---|
| platnosc.oczekuje | Klient poszedł do operatora (produkcja) | Płatność produkcyjna czeka na wynik u operatora. W piaskownicy to zdarzenie nie występuje. |
| platnosc.oplacona | Płatność zaksięgowana | Można wydać towar albo usługę. transakcja.oplacona ma czas księgowania, transakcja.metoda użytą metodę. |
| platnosc.odrzucona | Bank albo operator odmówił | Klient może spróbować ponownie z tego samego adres_platnosci (inną metodą albo kartą); wtedy dostaniesz kolejne zdarzenia tej samej płatności. |
| platnosc.zwrot | Zwrot wykonany albo zlecony | Treść ma dodatkowe pole zwrot (schemat Zwrot) z nowym zwrotem; transakcja.zwrocono i transakcja.status są już po zmianie. |
| platnosc.zwrot_odrzucony | Operator odrzucił zlecony zwrot | Kwota wraca do do_zwrotu, zwrot w polu zwrot ma status odrzucony. Dotyczy tylko produkcji. |
| platnosc_cykliczna.aktywna | Zgoda klienta i pierwsze obciążenie | Treść ma pole platnosc_cykliczna (schemat PlatnoscCykliczna) i transakcja pierwszego okresu. |
| platnosc_cykliczna.odnowiona | Kolejny okres opłacony | transakcja to obciążenie tego okresu, platnosc_cykliczna.nastepne_obciazenie to termin następnego. |
| platnosc_cykliczna.odmowa | Obciążenie odrzucone, będzie ponowione | platnosc_cykliczna.proby to liczba odmów w tym okresie, nastepne_obciazenie to termin ponowienia. |
| platnosc_cykliczna.wstrzymana | Ponowienia wyczerpane | Harmonogram stoi. Klient może podać nową kartę pod adres_zgody, wtedy przyjdzie platnosc_cykliczna.odnowiona. |
| platnosc_cykliczna.anulowana | Rezygnacja klienta albo sklepu | anulowana_przez to klient albo sklep. Kolejnych obciążeń nie będzie. |
Podpis, weryfikacja w PHP, Node i Pythonie, ponowienia i testowanie: przewodnik o webhookach.