Przejdź do treści
Oplac

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.

Tryb testowy

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.

JSON
{
  "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ń, gdzie data.object może być dowolnym typem.
  • livemode: true dla obiektów produkcyjnych, false dla 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()
Odpowiedź
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łówekZnaczenie
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.

Zamów integrację za darmo

BLIK, karty, subskrypcje i KSeF w jednym panelu.