Wedkarz.proAPI Documentationv1.1
REST API v1.1

Dokumentacja API Wedkarz.pro

Opis endpointów, autoryzacji i integracji dla aplikacji, systemów ERP/WMS oraz partnerów marketplace.

JSON over HTTPSBearer authWebhooksOpenAPI 3.1

1. Adres bazowy i wersjonowanie

Wszystkie integracje korzystają z wersjonowanego REST API. Numer wersji znajduje się w ścieżce, dzięki czemu klient może jawnie wskazać obsługiwaną wersję interfejsu.

Base URL: https://wedkarz.pro/api
API v1:   https://wedkarz.pro/api/v1
Health:   https://wedkarz.pro/api/v1/health
Integracje powinny korzystać wyłącznie z adresów https://wedkarz.pro/api/v1/.... Publiczna dokumentacja i specyfikacja OpenAPI są dostępne w tym portalu.

2. Autoryzacja

Endpointy prywatne przyjmują nieprzezroczysty access token w nagłówku Authorization. Access token domyślnie żyje 1 godzinę, refresh token 30 dni.

Logowanie

curl -X POST https://wedkarz.pro/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "sprzedawca@example.com",
    "password": "MOJE_HASLO",
    "device_name": "ERP magazyn"
  }'

Przykładowa odpowiedź:

{
  "data": {
    "user": {"id": 27, "role": "seller", "name": "Jan Kowalski"},
    "auth": {
      "token_type": "Bearer",
      "access_token": "vB4...",
      "expires_in": 3600,
      "refresh_token": "RX3...",
      "scopes": ["catalog:read", "products:write", "stock:write", "analytics:read"]
    }
  },
  "request_id": "..."
}

Rejestracja sprzedawcy przez API

POST /v1/auth/seller-register

{
  "name":"Jan Kowalski",
  "email":"sklep@example.com",
  "password":"MocneHaslo123!",
  "shop_name":"Sklep Wędkarski Jan",
  "legal_name":"Jan Kowalski Handel",
  "tax_id":"1234567890"
}

Konto otrzymuje rolę seller, a profil sprzedawcy status pending. Do wystawiania produktów potrzebna jest akceptacja administratora.

Użycie tokena

curl https://wedkarz.pro/api/v1/me \
  -H "Authorization: Bearer ACCESS_TOKEN"

Odświeżanie tokena

POST /v1/auth/refresh
Content-Type: application/json

{"refresh_token":"REFRESH_TOKEN"}
Refresh rotuje sesję: stary access/refresh token jest unieważniany, a klient powinien zapisać nową parę.

3. Role i uprawnienia

RolaMożliwości
buyerKatalog, koszyk, checkout, zamówienia, ulubione, alerty, opinie, wiadomości i zestawy społeczności.
sellerKatalog, własne oferty, ceny, stany, zdjęcia, wysyłka, zamówienia, statystyki, zestawy, synchronizacja ERP/WMS i webhooks.

Zakres dostępnych endpointów wynika z roli konta i uprawnień przypisanych do tokena.

4. Format odpowiedzi i błędów

Odpowiedzi sukcesu mają data, a listy dodatkowo meta i links.

{
  "data": [...],
  "meta": {"page":1,"limit":24,"total":29420,"pages":1226},
  "links": {"self":"...","next":"...","prev":null},
  "request_id":"f9b7..."
}

Błąd:

{
  "error": {
    "code": "insufficient_stock",
    "message": "Brak wymaganej ilości produktu.",
    "details": {"available": 2}
  },
  "request_id": "..."
}
HTTPZnaczenie
200Operacja zakończona
201Utworzono zasób
400Błędny JSON / brak Idempotency-Key / błędne żądanie
401Brak, wygasły lub niepoprawny token
403Token jest poprawny, ale rola nie ma uprawnień
404Zasób nie istnieje
409Konflikt, np. brak stanu lub powtórzony EAN
422Walidacja danych
429Limit żądań

5. Paginacja, filtrowanie i sortowanie

GET /v1/products?page=2&limit=48&category=14&brand=Shimano&available=1&sort=price_asc
GET /v1/products?q=stradic&price_from=200&price_to=900
GET /v1/catalog-products?q=5901234&category=18

Standardowe parametry: page, limit. Katalog ofert obsługuje także q, ean, category, brand, seller, available, price_from, price_to, sort.

6. Rate limiting

Standardowy limit API to 120 żądań/minutę dla tokena lub IP. Endpointy wrażliwe — logowanie, rejestracja, odświeżanie sesji, checkout i synchronizacja bulk — mają dodatkowe, niezależne limity ochronne.

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-Request-ID: 3d3f...

Jeśli limit zostanie przekroczony, API zwraca 429 Too Many Requests oraz nagłówek Retry-After z liczbą sekund do kolejnej bezpiecznej próby.

HTTP/1.1 429 Too Many Requests
Retry-After: 120

{
  "error": {
    "code": "login_temporarily_limited",
    "message": "Zbyt wiele nieudanych prób logowania. Spróbuj ponownie za chwilę.",
    "details": {"retry_after":120}
  }
}

Klient integracyjny powinien respektować Retry-After i stosować exponential backoff. W przypadku logowania mechanizm jest adaptacyjny: kilka pomyłek nie blokuje konta, a krótkie blokady pojawiają się dopiero po większej serii nieudanych prób.

7. Kategorie, marki i produkty

Drzewo kategorii

GET /v1/categories?tree=1

Marki

GET /v1/brands?q=shim

Oferty dostępne do zakupu

GET /v1/products

Wspólny katalog EAN

GET /v1/catalog-products

Pobranie produktu

GET /v1/products/123

Szczegóły zawierają m.in. cenę, stan, sprzedawcę, kategorię, obrazy, atrybuty techniczne, metody wysyłki i historię cen.

8. EAN jako główny identyfikator katalogowy

Jedna pozycja katalogowa może mieć wiele ofert sprzedawców. Najwygodniejszy endpoint integracyjny:

GET /v1/ean/5901234123457

Zwraca produkt wspólny, wszystkie aktywne oferty i najlepszą ofertę. Dzięki temu system ERP może sprawdzić, czy EAN istnieje przed jego wystawieniem.

9. Alerty i rekomendacje zakupowe

Alert cenowy

POST /v1/me/alerts
Authorization: Bearer ...
Content-Type: application/json

{"ean":"5901234123457","type":"price","target_price":199.99}

Alert dostępności

{"ean":"5901234123457","type":"availability"}

Co kupili inni

GET /v1/products/123/bought-together?limit=4

Rekomendacje opierają się na faktycznie opłaconych zamówieniach, a nie wyłącznie ręcznym przypisaniu.

10. Koszyk API

# dodaj 2 sztuki
POST /v1/cart/items
{"product_id":123,"quantity":2}

# pobierz koszyk
GET /v1/cart

# zmień ilość
PATCH /v1/cart/items/123
{"quantity":4}

# usuń
DELETE /v1/cart/items/123

# dostępne dostawy
GET /v1/cart/shipping-methods

Koszyk API jest przechowywany niezależnie od sesji przeglądarkowej i przypisany do konta kupującego.

11. Checkout i idempotency

Wymagane: każde POST /v1/checkout musi posiadać unikalny nagłówek Idempotency-Key. Ponowienie identycznego żądania z tym samym kluczem zwróci poprzedni wynik zamiast utworzyć drugie zamówienie.
curl -X POST https://wedkarz.pro/api/v1/checkout \
 -H "Authorization: Bearer ACCESS_TOKEN" \
 -H "Idempotency-Key: mobile-order-20260824-0001" \
 -H "Content-Type: application/json" \
 -d '{
   "first_name":"Jan",
   "last_name":"Kowalski",
   "street":"Leśna 10",
   "postal_code":"26-600",
   "city":"Radom",
   "email":"jan@example.com",
   "phone":"+48123456789",
   "payment_provider":"payu_marketplace",
   "shipping_method":{"12":31,"18":44},
   "pickup_point_code":{"12":"RAD01A"},
   "pickup_point_name":{"12":"Paczkomat RAD01A"},
   "pickup_point_address":{"12":"ul. Przykładowa 1, Radom"}
 }'

Klucze w shipping_method to ID sprzedawców, a wartości to ID metod wysyłki. W przypadku Paczkomatu podaj odpowiadające pola punktu odbioru.

12. Zamówienia, zwroty i spory

GET
/v1/ordersHistoria zakupów kupującego
GET
/v1/orders/{id}Zamówienie wraz z częściami sprzedawców, produktami i płatnościami
POST
/v1/orders/{id}/returnsWniosek o zwrot dla seller_order_id
POST
/v1/orders/{id}/disputesSpór lub zgłoszenie

13. API sprzedawcy — wystawianie produktów

Najważniejszy scenariusz integracji z ERP: EAN → sprawdzenie katalogu → wystawienie oferty.

Produkt istnieje już w katalogu

POST /v1/seller/products
Authorization: Bearer SELLER_TOKEN
Content-Type: application/json

{
  "ean":"5901234123457",
  "price":249.90,
  "stock":17,
  "sku":"MAG-00192",
  "external_id":"SUBIEKT-TOWAR-192",
  "description":"Opis mojej oferty",
  "dispatch_min_days":1,
  "dispatch_max_days":2,
  "status":"active"
}

Nazwa, kategoria, marka i parametry wspólne są pobierane automatycznie z katalogu EAN.

EAN nie istnieje

{
  "ean":"5909999000001",
  "name":"Nowa przynęta 12 cm",
  "category_id":83,
  "brand":"Przykładowa Marka",
  "price":34.99,
  "stock":50,
  "shipping_weight":0.15,
  "attributes":{"dlugosc":"12","kolor":"Fire Tiger"}
}

Nowy EAN tworzy ofertę pending i zgłoszenie do wspólnego katalogu, zgodnie z zasadami moderacji portalu.

Aktualizacja ceny i stanu

PATCH /v1/seller/products/123

{"price":239.90,"stock":22}

Zmiany zapisują historię ceny, ruch magazynowy oraz mogą uruchomić alerty klientów.

Zdjęcia

curl -X POST https://wedkarz.pro/api/v1/seller/products/123/images \
 -H "Authorization: Bearer SELLER_TOKEN" \
 -F "images[]=@front.jpg" \
 -F "images[]=@detail.webp"

14. Synchronizacja ERP / WMS — bulk, external_id i delta sync

API v1.1 jest przygotowane do dwukierunkowej integracji z Subiektem, WAPRO, systemem magazynowym, PIM-em lub własnym ERP. Każda oferta sprzedawcy może mieć stabilny external_id pochodzący z systemu zewnętrznego.

Przypisanie external_id

PATCH /v1/seller/products/123
{
  "external_id":"SUBIEKT-TOWAR-7788"
}

Później rekord można pobrać bez znajomości ID Wedkarz.pro:

GET /v1/seller/products/external/SUBIEKT-TOWAR-7788

Masowa aktualizacja do 500 produktów

PATCH /v1/seller/products/bulk
{
  "atomic": false,
  "items": [
    {"external_id":"SUB-1001","stock":12,"price":149.99},
    {"ean":"5901234567890","stock":0},
    {"product_id":123,"set_external_id":"SUB-7788","price":99.90}
  ]
}

atomic:false zwraca wynik każdej pozycji osobno i nie blokuje poprawnych rekordów przez jeden błąd. atomic:true wycofuje całą paczkę przy pierwszym błędzie. Są też skrócone endpointy PATCH /v1/seller/inventory/bulk i PATCH /v1/seller/prices/bulk.

Delta sync przez updated_since

GET /v1/seller/sync?updated_since=2026-08-24T08:00:00Z&limit=200

Odpowiedź zawiera osobno zmienione produkty i zamówienia oraz niezależne kursory next_updated_since i next_after_id. Pierwsze wywołanie może użyć wspólnego updated_since. Gdy has_more=true, dla kolejnych stron przekaż odpowiednio products_since/products_after_id oraz orders_since/orders_after_id. Dzięki temu szybciej zmieniająca się kolekcja nie przesunie kursora drugiej.

GET /v1/seller/products?updated_since=2026-08-24T10:00:00+02:00&updated_after_id=1822&limit=500
GET /v1/seller/orders?updated_since=2026-08-24T10:00:00+02:00&updated_after_id=918&include_items=1

External ID zamówienia

Po zaimportowaniu zamówienia do ERP możesz zapisać jego numer wewnętrzny:

PATCH /v1/seller/orders/812
{"external_id":"ERP-ZAM-2026-991"}

Potem: GET /v1/seller/orders/external/ERP-ZAM-2026-991. Szczegóły zamówienia sprzedawcy zawierają pozycje oraz adres dostawy potrzebny do realizacji.

Zalecany model synchronizacji: webhook seller_order.created uruchamia szybki import nowego zamówienia, a cykliczne GET /v1/seller/sync co kilka minut pełni rolę mechanizmu naprawczego i synchronizuje wszystko, co mogło zostać pominięte.

15. Statystyki zainteresowania i sugestia ceny

GET /v1/seller/products/123/stats
{
  "data": {
    "views": 1840,
    "cart_adds": 92,
    "favorites": 41,
    "active_alerts": 18,
    "purchases": 37,
    "revenue": 8876.30,
    "conversion": 2.01,
    "price_suggestion": {
      "current_price":249.90,
      "competitor_count":3,
      "market_min":239.90,
      "suggested_price":239.89,
      "position":"above_market"
    }
  }
}

Zbiorczy dashboard sklepu: GET /v1/seller/analytics?days=30.

16. Wysyłka i realizacja zamówień

GET  /v1/seller/shipping-methods
POST /v1/seller/shipping-methods
PATCH /v1/seller/shipping-methods/31
DELETE /v1/seller/shipping-methods/31

GET   /v1/seller/orders?status=processing
PATCH /v1/seller/orders/812
{"status":"shipped","tracking_number":"123456789"}

Zmiana statusu przez API generuje także zdarzenie webhook seller_order.status.updated.

17. Gotowe i społecznościowe zestawy

Zestaw sprzedawcy

POST /v1/seller/bundles
{
  "name":"Gotowy zestaw na szczupaka",
  "description":"Kompletny zestaw startowy",
  "status":"active",
  "items":[
    {"product_id":101,"quantity":1},
    {"product_id":102,"quantity":1},
    {"product_id":103,"quantity":2}
  ]
}

Sprzedawca może używać tylko własnych aktywnych ofert. Kupujący ma analogiczne endpointy /v1/community/bundles do zestawów społeczności.

18. Webhooks

Webhook musi korzystać z HTTPS. Przy utworzeniu API zwraca sekret tylko raz.

POST /v1/webhooks
{
  "url":"https://erp.example.com/hooks/wedkarz",
  "events":["seller_order.created","product.stock.updated","products.bulk.updated","seller_order.status.updated"],
  "description":"ERP produkcja"
}

Dostępne zdarzenia

ZdarzenieKiedy
order.createdPowstało zamówienie — przez API lub zwykły sklep WWW
seller_order.createdPowstała część zamówienia przeznaczona dla konkretnego sprzedawcy
order.updatedZmiana danych lub statusu zamówienia
product.createdNowa oferta sprzedawcy
product.updatedOgólna zmiana oferty
product.price.updatedZmiana ceny
product.stock.updatedZmiana stanu magazynowego
product.status.updatedZmiana statusu oferty
products.bulk.updatedZakończona paczka bulk lub import CSV
seller_order.status.updatedZmiana realizacji, trackingu lub external_id
webhook.testRęczny test

Od v1.1 webhooki kluczowych zamówień i zmian wykonywanych w panelu WWW również trafiają do integracji. Zalecamy mimo to okresowy delta sync jako zabezpieczenie.

Weryfikacja podpisu HMAC

Nagłówki:

X-Wedkarz-Webhook-Version: 1.1
X-Wedkarz-Event: product.stock.updated
X-Wedkarz-Event-Id: uuid
X-Wedkarz-Signature: sha256=...
// PHP
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $webhookSecret);
if (!hash_equals($expected, $_SERVER['HTTP_X_WEDKARZ_SIGNATURE'] ?? '')) {
    http_response_code(401); exit;
}

19. Kompletne przykłady integracji

JavaScript / fetch

const API = 'https://wedkarz.pro/api';
const login = await fetch(`${API}/v1/auth/login`, {
  method: 'POST',
  headers: {'Content-Type':'application/json'},
  body: JSON.stringify({email, password, device_name:'Panel partnera'})
}).then(r => r.json());

const token = login.data.auth.access_token;
const products = await fetch(`${API}/v1/products?q=shimano&limit=24`, {
  headers: {Authorization: `Bearer ${token}`}
}).then(r => r.json());

PHP / cURL

$ch = curl_init('https://wedkarz.pro/api/v1/seller/products/123');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $token,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['price'=>229.99,'stock'=>14]),
]);
$response = json_decode(curl_exec($ch), true);

Python / requests

import requests

API = "https://wedkarz.pro/api/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {token}"

r = s.get(f"{API}/seller/orders", params={"status":"processing"})
r.raise_for_status()
for order in r.json()["data"]:
    print(order["number"], order["subtotal"])

Gotowe pliki są również w katalogu /examples/ tej dokumentacji.

20. OpenAPI i Postman

Interaktywna dokumentacja

Swagger UI / Try it out

OpenAPI 3.1 JSON

openapi.json

OpenAPI YAML

openapi.yaml

21. Zasady bezpieczeństwa