Przejdź do treści

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_..., produkcyjny plc_live_.... Klucz testowy widzi wyłącznie transakcje testowe, produkcyjny wyłącznie produkcyjne. Klucze wydajesz w panelu (Integracja).
  • Kwoty zawsze w groszach (najmniejszej jednostce waluty): 12900 to 129,00 zł. Nigdy ułamki.
  • Treść zapytań: JSON (Content-Type: application/json). Formularz application/x-www-form-urlencoded też 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ść.

Dane testowe, scenariusze i przejście na produkcję.

Uwierzytelnianie
curl "https://placenie.pl/api/v1/platnosci?limit=1" \
  -H "Authorization: Bearer plc_test_..."
Nagłówki każdej odpowiedzi
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
Obiekt błędu
{
    "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"
    }
}
Stronicowanie kursorem
# 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 1 do 255

Przykł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-01 2026-10-03

Treść żądania (JSON)

kwota integer wymagane

Kwota w groszach (najmniejszej jednostce waluty). Od 1,00 do 999 999,99.

od 100 do 99999999

Przykład: 12900

waluta Waluta domyślnie PLN

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykł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 120

Przykł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 albo GET /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 50

Przykład: { "koszyk": "c_8812", "klient_crm": "4471" }

Odpowiedzi

200
Istniejąca płatność o tym samym numer_zamowienia, kwocie i walucie (albo powtórka z Idempotency-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 z Retry-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']}")
Odpowiedź 201
{
    "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: nowa oczekuje oplacona odrzucona zwrocona

metoda Metoda

Tylko płatności tą metodą.

Wartości: blik card transfer

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 1 do 100

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 po albo przed.

od 1

Odpowiedzi

200
Lista płatności. Treść: Lista z dane jako lista Platnosc
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 z Retry-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']}")
Odpowiedź 200
{
    "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 z Retry-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']}")
Odpowiedź 200
{
    "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 1 do 255

Przykład: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c

Treść żądania (JSON)

opis string, nullable

do 255

metadane object, nullable

Scalane z istniejącymi; null przy 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 z Retry-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']}")
Odpowiedź 200
{
    "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 1 do 255

Przykł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 1

Przykł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 ponad do_zwrotu) albo złe pola. Treść: Blad
429
Przekroczony limit zapytań (limit_zapytan). Ponów po czasie z Retry-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']}")
Odpowiedź 201
{
    "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"
        }
    ]
}
Treść pelny
[]

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: oplacona odrzucona

metoda Metoda

Metoda zapisana przy płatności. Domyślnie wybrana wcześniej na ekranie albo blik.

Wartości: blik card transfer

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 z Retry-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']}")
Odpowiedź 200
{
    "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": []
}
Treść odmowa
{
    "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 1 do 255

Przykład: 0f9d4c2a-6b3e-4e1a-9c7d-2b8f1e3a5d6c

Treść żądania (JSON)

kwota integer wymagane

Kwota każdego obciążenia w groszach.

od 100 do 99999999

waluta Waluta

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykład: PLN

okres string (enum) wymagane

Wartości: tydzien miesiac kwartal rok

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 50

Przykł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 z Retry-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 1 do 100

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 po albo przed.

od 1

status StatusPlatnosciCyklicznej

Wartości: oczekuje aktywna ponawiana wstrzymana anulowana

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 z Retry-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 z Retry-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 1 do 255

Przykł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 z Retry-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: oplacona odrzucona

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 z Retry-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.oczekuje platnosc.oplacona platnosc.odrzucona platnosc.zwrot platnosc.zwrot_odrzucony platnosc_cykliczna.aktywna platnosc_cykliczna.odnowiona platnosc_cykliczna.odmowa platnosc_cykliczna.wstrzymana platnosc_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 1 do 100

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 po albo przed.

od 1

Odpowiedzi

200
Lista zdarzeń. Treść: Lista z dane jako lista Zdarzenie
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 z Retry-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']}")
Odpowiedź 200
{
    "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 z Retry-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']}")
Odpowiedź 200
{
    "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 z Retry-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']}")
Odpowiedź 202
{
    "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

Obiekt Metadane
{
    "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 100 do 99999999

Przykład: 12900

waluta Waluta domyślnie PLN

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykł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 120

Przykł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 albo GET /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 50

Przykład: { "koszyk": "c_8812", "klient_crm": "4471" }

ZmianaPlatnosci#

Pola

opis string, nullable

do 255

metadane object, nullable

Scalane z istniejącymi; null przy kluczu usuwa ten klucz.

NowyZwrot#

Pola

kwota integer

Kwota zwrotu w groszach. Bez tego pola zwrot całej kwoty pozostałej do zwrotu.

od 1

Przykład: 2900

Symulacja#

Pola

wynik string (enum) wymagane

Wynik, który ma dostać płatność.

Wartości: oplacona odrzucona

metoda Metoda

Metoda zapisana przy płatności. Domyślnie wybrana wcześniej na ekranie albo blik.

Wartości: blik card transfer

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. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykład: PLN

status StatusZwrotu wymagane

wykonany zakończony, zlecony czeka u operatora (produkcja), odrzucony operator odmówił (kwota wróciła do puli).

Wartości: wykonany zlecony odrzucony

zrodlo string (enum) wymagane

Skąd zlecono zwrot.

Wartości: api panel

utworzony string (date-time) wymagane
Obiekt Zwrot
{
    "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

test to piaskownica (klucz plc_test_), live to produkcja (klucz plc_live_).

Wartości: test live

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: nowa oczekuje oplacona odrzucona zwrocona

kwota integer wymagane

Kwota w groszach.

waluta Waluta wymagane

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykł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: blik card transfer

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 50

Przykł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; null przed zapłatą.

zwroty array<Zwrot> wymagane

Zwroty w kolejności zlecenia.

Obiekt Platnosc
{
    "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 100 do 99999999

waluta Waluta

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykład: PLN

okres string (enum) wymagane

Wartości: tydzien miesiac kwartal rok

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 50

Przykł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

test to piaskownica (klucz plc_test_), live to produkcja (klucz plc_live_).

Wartości: test live

status StatusPlatnosciCyklicznej wymagane

Wartości: oczekuje aktywna ponawiana wstrzymana anulowana

kwota integer wymagane
waluta Waluta wymagane

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

od 3 do 3

Przykład: PLN

okres string (enum) wymagane

Wartości: tydzien miesiac kwartal rok

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 50

Przykł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: klient sklep

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.oczekuje platnosc.oplacona platnosc.odrzucona platnosc.zwrot platnosc.zwrot_odrzucony platnosc_cykliczna.aktywna platnosc_cykliczna.odnowiona platnosc_cykliczna.odmowa platnosc_cykliczna.wstrzymana platnosc_cykliczna.anulowana

tryb Tryb wymagane

test to piaskownica (klucz plc_test_), live to produkcja (klucz plc_live_).

Wartości: test live

utworzone string (date-time) wymagane
transakcja Platnosc wymagane

Płatność (transakcja). Ta sama postać w odpowiedziach API i w polu transakcja zdarzenia.

zwrot Zwrot

Tylko przy platnosc.zwrot i platnosc.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: czeka dostarczony porzucony

proby integer
ostatni_kod integer, nullable

Kod HTTP ostatniej odpowiedzi odbiornika.

ostatni_blad string, nullable
nastepna_proba string (date-time), nullable
Obiekt Zdarzenie
{
    "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
{
    "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_nieprawidlowe uwierzytelnienie nie_znaleziono plan operator konflikt limit zadanie_nieprawidlowe blad_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.

Obiekt Blad
{
    "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.

TypWartościOpis
Tryb testlive

test to piaskownica (klucz plc_test_), live to produkcja (klucz plc_live_).

Waluta string

Kod ISO 4217. PLN w każdym planie; EUR, USD, GBP, CZK w planie Skala i Enterprise.

Metoda blikcardtransfer

blik to BLIK, card karta, transfer szybki przelew (pay-by-link).

StatusPlatnosci nowaoczekujeoplaconaodrzuconazwrocona
  • 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.
StatusZwrotu wykonanyzleconyodrzucony

wykonany zakończony, zlecony czeka u operatora (produkcja), odrzucony operator odmówił (kwota wróciła do puli).

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 zdarzeniaKiedyOpis
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.