Dla programistów

Dokumentacja API

REST API do integracji dowolnego sklepu z ReturnBasis — także takiego, który nie ma gotowej integracji (Shoper, WooCommerce, BaseLinker, Allegro). Przyjmujesz zgłoszenie u siebie, a od nas bierzesz przesyłki zwrotne, statusy i obsługę sprawy. Zmiany odbierasz przez API albo webhooki.

Wprowadzenie

Wszystkie adresy są względem bazowego URL. Ciała żądań i odpowiedzi są w formacie JSON (pola w konwencji snake_case). Wszystkie kwoty podajemy i przyjmujemy w groszach — pieniądze nigdy nie przechodzą przez liczby zmiennoprzecinkowe.

Base URL: https://returnbasis.com/api/v1

Najkrótsza integracja to jedno wywołanie w chwili, gdy kupujący zgłasza zwrot w Twoim panelu. W odpowiedzi dostajesz tracking_url — link, pod którym on wybierze przewoźnika i odbierze kod nadania:

curl https://returnbasis.com/api/v1/returns \
  -H "Authorization: Bearer rtb_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "WITHDRAWAL",
    "order_ref": "ZAM-1001",
    "delivered_at": "2026-08-12T10:00:00Z",
    "customer": { "name": "Anna Kowalska", "email": "anna@example.com" },
    "items": [
      { "external_id": "SKU-12", "name": "Buty trekkingowe", "quantity": 1,
        "unit_price": 29900, "reason": "za-duzy-rozmiar" }
    ]
  }'

Uwierzytelnianie

Każde żądanie (poza openapi.json) wymaga klucza API w nagłówku Authorization. Klucz wygenerujesz w panelu: Ustawienia → API. Pełną wartość widać tylko raz — przechowuj ją bezpiecznie po stronie serwera i nigdy w kodzie front-endu.

Authorization: Bearer rtb_xxxxxxxxxxxxxxxxxxxxxxxx

Sprawdź, czy klucz działa:

curl https://returnbasis.com/api/v1/me -H "Authorization: Bearer rtb_TWOJ_KLUCZ"
{
  "organization": { "name": "Buty i Plecaki", "slug": "buty-i-plecaki",
                    "return_form_url": "/sklep/buty-i-plecaki/zwrot" },
  "policy": { "return_days": 30, "refund_days": 14, "shipping_payer": "mixed" },
  "plan": { "key": "PRO", "status": "active", "returns_monthly": 3000, "returns_left": 2841 },
  "stats": { "returns_total": 159, "returns_open": 12, "shipment_credits": 25 }
}

Limity i wersjonowanie

  • Rate limit: ~60–120 żądań na minutę na IP, zależnie od endpointu. Przekroczenie zwraca 429 z kodem rate_limited.
  • Limit zwrotów: miesięczny, zależny od planu. Po wyczerpaniu tworzenie zwrotów zwraca 402; odczyt istniejących spraw działa dalej.
  • Wersja: aktualna to 2026-08-24, zwracana w nagłówku X-ReturnBasis-Api-Version. Zmiany łamiące kompatybilność wprowadzimy jako nową ścieżkę wersji, nie po cichu.

Błędy

Błędy mają stały kształt z maszynowo czytelnym kodem:

{ "error": { "code": "quota_exceeded", "message": "Wyczerpany miesięczny limit zwrotów (3000)." } }
PoleTypOpis
unauthorized / invalid_key401Brak lub nieprawidłowy klucz API.
quota_exceeded402Wyczerpany miesięczny limit zwrotów w planie.
not_found404Zasób nie istnieje.
invalid_body / invalid_param400Nieprawidłowe dane wejściowe.
rate_limited429Za dużo żądań — zwolnij.
server_error500Błąd po naszej stronie.

Zwroty

Zgłoszenie zwrotu przez API zachowuje się dokładnie tak samo jak wypełnienie publicznego formularza: kupujący dostaje maila z potwierdzeniem i linkiem, sprawa trafia do panelu, a przy kind: "WITHDRAWAL" zapisujemy datę oświadczenia o odstąpieniu — od niej biegnie Twój ustawowy termin na zwrot pieniędzy.

POST/returnswymaga klucza
PoleTypOpis
kindstringWITHDRAWAL (domyślnie), EXCHANGE albo COMPLAINT.
order_refstringNumer zamówienia w Twoim sklepie.
delivered_atdate-timeData doręczenia zamówienia — od niej liczymy termin na odstąpienie. Podawaj, jeśli ją znasz.
customerwymaganeobjectname, email, opcjonalnie phone.
itemswymaganearrayPozycje: name, opcjonalnie external_id, sku, quantity, unit_price (grosze), reason.
{
  "id": "cmsn…",
  "number": "ZW-2026-000123",
  "tracking_url": "https://returnbasis.com/zwrot/…",
  "status": "accepted",
  "status_label": "Przyjęty",
  "shipment": null
}
GET/returnswymaga klucza

Stronicowanie kursorem, nie offsetem — lista rośnie w trakcie przeglądania, a offset gubiłby albo dublował rekordy. Parametry: status (kod statusu albo open), order_ref, since, limit (do 100), cursor.

{
  "data": [ { "number": "ZW-2026-000123", "status": "in_transit", … } ],
  "has_more": true,
  "next_cursor": "cmsn…"
}
GET/returns/{number}wymaga klucza

Jeden zwrot po numerze widocznym dla kupującego (ZW-2026-000123) — to on figuruje w Twoim systemie i w korespondencji, więc po nim adresujemy.

{
  "number": "ZW-2026-000123",
  "kind": "withdrawal",
  "status": "delivered",
  "status_label": "Doręczony",
  "withdrawal_at": "2026-08-20T09:12:00.000Z",
  "items": [
    { "name": "Buty trekkingowe", "quantity": 1, "unit_price": 29900,
      "reason": "za-duzy-rozmiar", "decision": "pending" }
  ],
  "shipment": {
    "carrier": "inpost_locker",
    "carrier_label": "Paczkomat InPost 24/7",
    "status": "delivered",
    "payer": "customer",
    "price": 1599,
    "dispatch_code": "7KP-M42-QX9",
    "tracking_number": "6800123456789"
  },
  "refund": { "method": "original", "amount": null, "shipping_refunded": true }
}

Numer konta do zwrotu pieniędzy nie jest częścią API. Leży w bazie zaszyfrowany (AES-256-GCM) i widzi go wyłącznie zespół sklepu w panelu — nie wychodzi też do eksportu CSV.

Statystyki

GET/summarywymaga klucza

Zbiorcze liczby do własnego dashboardu — bez przeciągania całej listy zgłoszeń.

{
  "totals": { "returns": 159, "open": 12, "refunded": 131,
              "refunded_amount": 4218900, "last_30_days": 24 },
  "by_status": [ { "status": "delivered", "label": "Doręczony", "count": 4 } ],
  "top_reasons": [ { "reason": "za-duzy-rozmiar", "count": 41 } ]
}

Webhooki

Zamiast odpytywać API, zarejestruj adres URL — wyślemy na niego żądanie POST za każdym razem, gdy zajdzie subskrybowane zdarzenie. Zdarzenia: return.created, return.status, return.refunded, shipment.ready i shipment.delivered. Webhooki możesz też dodać w panelu (Ustawienia → API).

POST/webhookswymaga klucza

URL musi być publiczny i po HTTPS. Pole secret zwracamy tylko w tej odpowiedzi — zapisz je.

curl https://returnbasis.com/api/v1/webhooks \
  -H "Authorization: Bearer rtb_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://sklep.pl/hooks/returnbasis",
        "events": ["return.created", "return.status"] }'
{ "id": "cmsn…", "url": "https://sklep.pl/hooks/returnbasis", "events": ["return.created","return.status"], "enabled": true, "secret": "whsec_…" }

Ładunek dostarczany na Twój URL:

{
  "id": "evt_…",                 // stałe dla zdarzenia — obsługuj idempotentnie
  "event": "return.status",
  "created_at": "2026-08-24T12:00:00.000Z",
  "api_version": "2026-08-24",
  "data": { /* obiekt zwrotu jak w GET /returns/{number} */ }
}

Weryfikacja podpisu

Każda dostawa ma nagłówek X-ReturnBasis-Signature: sha256=… — to HMAC-SHA256 surowego ciała żądania, kluczowany sekretem webhooka. Zweryfikuj go, zanim zaufasz danym:

import crypto from "crypto";

function verify(rawBody, signature, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret)
    .update(rawBody, "utf8").digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Dostawa jest best-effort z krótkim timeoutem; odpowiedz kodem 2xx. Ostatni status i licznik błędów widać w panelu i w GET /webhooks. Ze względu na możliwe ponowienia — obsługuj zdarzenia po ich id idempotentnie.

OpenAPI

Pełna specyfikacja maszynowa (OpenAPI 3.1) jest dostępna publicznie — zaimportuj ją do Postmana, Insomnii albo wygeneruj z niej klienta SDK:

https://returnbasis.com/api/v1/openapi.json

Zacznij integrację

Załóż konto, wygeneruj klucz w Ustawienia → API i zgłoś pierwszy zwrot. 14 dni bezpłatnie.

Załóż konto