Podstawy API
Konwencje
Każdy obiekt API wygląda tak samo: ma id ze stałym przedrostkiem, object z nazwą typu, livemode, created i metadata. Kwoty są w groszach, czas w sekundach Unix, listy w jednej kopercie.
Klucz testowy w przykładach
Wklej klucz sk_test_ z panelu (zakładka Deweloperzy), a każdy przykład będzie gotowy do uruchomienia. Klucz zostaje w tej karcie przeglądarki, nie wysyłamy go nigdzie.
Przykłady używają Twojego klucza testowego. Produkcyjnego klucza nie przyjmujemy.
JSON, HTTPS, kodowanie#
Żądania POST wysyłasz jako JSON z nagłówkiem Content-Type: application/json. Odpowiedzi są zawsze JSON w UTF-8 z polskimi znakami bez ucieczek, także dla błędów 404 i 500 (nigdy strona HTML). Pola, których nie znasz, pomijaj: w kolejnych wersjach mogą dojść nowe pola i nowe typy zdarzeń bez zmiany wersji API. Pole o wartości null jest obecne w odpowiedzi, a nie pominięte, więc możesz na nim polegać w mapowaniu typów.
{
"id": "pay_Ab12Cd34Ef56Gh",
"object": "payment",
"amount": 12900,
"currency": "PLN",
"status": "pending",
"method": null,
"metadata": {"order_id": "10482"},
"livemode": false,
"created": 1760000000
}
Kwoty w groszach#
Każda kwota (amount, amount_refunded, application_fee, net, gross, amount_due) to liczba całkowita w najmniejszej jednostce waluty: 12900 to 129,00 zł, 100 to 1,00 zł. Minimalna kwota płatności to 100. Dzięki temu nie ma błędów zaokrągleń typów zmiennoprzecinkowych. Waluta to kod ISO 4217 wielkimi literami: PLN, a od planu Skala także EUR i USD. Kwota w EUR i USD liczy się do limitu obrotu planu po przybliżonym kursie.
Czas jako znacznik Unix#
Daty i godziny to liczby całkowite sekund od 1 stycznia 1970 UTC: created, paid_at, expires_at, current_period_start, current_period_end, trial_end, canceled_at, delivered_at. Wyjątkiem są daty faktur issue_date i due_date w postaci RRRR-MM-DD, bo tak wymaga ich prawo i KSeF. Filtry list po czasie przyjmują znacznik Unix: created[gte]=1760000000.
PHP
- Z sekund Unix
(new DateTimeImmutable('@1760000000'))- Na sekundy Unix
time()
Node
- Z sekund Unix
new Date(1760000000 * 1000)- Na sekundy Unix
Math.floor(Date.now() / 1000)
Python
- Z sekund Unix
datetime.fromtimestamp(1760000000, tz=timezone.utc)- Na sekundy Unix
int(time.time())
Identyfikatory i przedrostki#
Identyfikator ma stały przedrostek z nazwą typu, więc po samym id widać, czym obiekt jest. Identyfikatory są tekstami: nie parsuj ich, nie zakładaj długości, przechowuj w kolumnie do 64 znaków.
pay_
- Obiekt
- payment
- Przedrostek
plan_- Obiekt
- plan
plink_
- Obiekt
- payment_link
- Przedrostek
coupon_- Obiekt
- coupon
re_
- Obiekt
- refund
- Przedrostek
sub_- Obiekt
- subscription
cus_
- Obiekt
- customer
- Przedrostek
inv_- Obiekt
- invoice
evt_
- Obiekt
- event
- Przedrostek
we_- Obiekt
- webhook_endpoint
acct_
- Obiekt
- account
- Przedrostek
req_- Obiekt
- identyfikator żądania (nie obiekt)
Pola w każdym obiekcie#
object: nazwa typu (payment,customer,list). Przydaje się przy obsłudze zdarzeń, gdziedata.objectmoże być dowolnym typem.livemode:truedla obiektów produkcyjnych,falsedla piaskownicy. Sprawdzaj go w odbiorcy webhooka, zanim zmienisz stan prawdziwego zamówienia.created: chwila utworzenia jako znacznik Unix.metadata: Twoje własne pary klucz: wartość, opisane niżej.
Pola z identyfikatorem innego obiektu (customer, payment, plan) zwracają sam identyfikator, a po dodaniu expand[] pełny obiekt. Szczegóły w Rozwijanie obiektów.
Metadata#
Pole metadata ma każdy zasób, który tworzysz: płatność, link, zwrot, klient, plan, kupon, subskrypcja, faktura. Mieści do 50 kluczy; klucz ma do 40 znaków, wartość to tekst do 500 znaków (liczby i wartości logiczne są zapisywane jako tekst). Wraca w obiekcie i w każdym zdarzeniu webhooka, dlatego to najlepsze miejsce na numer zamówienia albo identyfikator z Twojego CRM.
Zmiana przez POST /{id} łączy klucze z już zapisanymi: nowe dochodzą, podane nadpisują, wartość null albo pusty tekst usuwa klucz, a "metadata": "" czyści wszystko. Przekroczenie limitów kończy się 400 metadata_invalid. Nie zapisuj w metadata danych kart ani haseł; to pole jest widoczne w panelu i w zdarzeniach.
curl https://oplac.pl/api/v1/payments/pay_Ab12Cd34Ef56Gh \
-H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
-H "Content-Type: application/json" \
-d '{"metadata": {"order_id": "10482", "crm_id": "7", "kupon": null}}'
$ch = curl_init('https://oplac.pl/api/v1/payments/pay_Ab12Cd34Ef56Gh');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TWOJ_KLUCZ', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['metadata' => ['order_id' => '10482', 'crm_id' => '7', 'kupon' => null]]),
CURLOPT_RETURNTRANSFER => true,
]);
$payment = json_decode(curl_exec($ch), true);
const res = await fetch('https://oplac.pl/api/v1/payments/pay_Ab12Cd34Ef56Gh', {
method: 'POST',
headers: { Authorization: 'Bearer sk_test_TWOJ_KLUCZ', 'Content-Type': 'application/json' },
body: JSON.stringify({ metadata: { order_id: '10482', crm_id: '7', kupon: null } }),
});
const payment = await res.json();
import requests
res = requests.post(
"https://oplac.pl/api/v1/payments/pay_Ab12Cd34Ef56Gh",
headers={"Authorization": "Bearer sk_test_TWOJ_KLUCZ"},
json={"metadata": {"order_id": "10482", "crm_id": "7", "kupon": None}},
)
payment = res.json()
HTTP/1.1 200 OK
{
"id": "pay_Ab12Cd34Ef56Gh",
"object": "payment",
"metadata": {"order_id": "10482", "crm_id": "7"},
"livemode": false
}
Listy#
Każda lista to obiekt {object: "list", url, has_more, data} z elementami od najnowszego. has_more mówi, czy są kolejne strony; url to ścieżka listy bez parametrów. Stronicowanie kursorem (limit, starting_after, ending_before) i filtry opisuje Stronicowanie.
Nagłówki odpowiedzi#
| Nagłówek | Znaczenie |
|---|---|
X-Request-Id | identyfikator żądania req_, ten sam co w treści błędu; podaj go w zgłoszeniu |
Oplac-Version | użyta wersja API |
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset | limit zapytań na sekundę, ile zostało, za ile sekund okno się odnawia |
Retry-After | przy 429: za ile sekund ponowić |
Idempotent-Replayed, Original-Request | odpowiedź odtworzona z zapisu idempotencji i identyfikator pierwszego żądania |
Powiązane
Klucz testowy dostajesz od razu po zapisie
Adres e-mail, kod z maila i piaskownica z kodami BLIK. Produkcję włączasz sam w panelu: plan, dostawca płatności, klucz sk_live_. Wolisz, żeby wdrożenie w sklepie zrobił nasz zespół? To też jest za darmo.