Szybki start
Konto i zamówienia
Załóż konto sprzedawcy. API włącza się automatycznie po 10 opłaconych zamówieniach. Wcześniejszy dostęp do katalogu możemy włączyć ręcznie: napisz na czacie w panelu.
Klucz w panelu
W panelu sprzedawcy otwórz zakładkę 🔌 API i kliknij „Wygeneruj klucz API”. Klucz pokazujemy tylko raz, więc od razu zapisz go w bezpiecznym miejscu.
Pierwsze zapytanie
Wyślij zapytanie z kluczem w nagłówku X-API-Key. Odpowiedź przyjdzie w formacie JSON.
curl -H "X-API-Key: dsk_twój_klucz" \
"https://dropshippers.pl/api/v1/products?limit=100"
Klucz API
Każde zapytanie wysyłasz z nagłówkiem X-API-Key: twój_klucz. Działa też Authorization: Bearer twój_klucz. Klucza w adresie URL nie przyjmujemy, bo adresy trafiają do logów i historii przeglądarki.
- Jeden klucz na konto. Wygenerowanie nowego od razu unieważnia poprzedni.
- Tylko na serwerze. API jest przeznaczone do połączeń serwer z serwerem. Przeglądarka nie odczyta odpowiedzi z kodu strony WWW, więc klucza nie umieszczaj w kodzie sklepu.
- Klucz działa niezależnie od hasła do panelu. Zmiana hasła go nie unieważnia, a unieważnienie klucza nie wyloguje Cię z panelu.
- Wyciek? Wygeneruj nowy klucz w zakładce 🔌 API. Stary przestaje działać natychmiast.
Endpointy
Adres bazowy: https://dropshippers.pl/api/v1. Wszystkie endpointy tylko odczytują dane.
| Metoda i adres | Co zwraca |
|---|---|
| GET /feed.xml, GET /feed.csv | Cały katalog jako plik do importu. Autoryzacja tokenem pliku, nie kluczem API (opis niżej, w sekcji Plik XML i CSV). |
| GET /products | Produkty z katalogu, te same, które widzisz w panelu w zakładce Nowe zamówienie. Stronicowanie kursorem. |
| GET /products/{id} | Jeden produkt po ID albo kodzie, np. /products/123 lub /products/DS-123. |
| POST, GET /orders | Zamówienia przez API (po włączeniu), opis niżej w sekcji Zamówienia przez API. |
Lista produktów
| Parametr | Opis |
|---|---|
| limit | Liczba produktów na stronie. Domyślnie 50, maksymalnie 100. |
| cursor | Wartość next_cursor z poprzedniej odpowiedzi. Pobieraj kolejne strony, dopóki has_more jest true. |
| updated_since | Tylko produkty zmienione od podanej chwili, format ISO 8601, np. 2026-10-16T08:00:00Z. Bez strefy czasowej przyjmujemy UTC. |
| code | Jeden produkt po kodzie, np. DS-123. |
{
"data": [
{
"id": 123,
"code": "DS-123",
"name": "Torebka damska",
"description_text": "Opis produktu…",
"description_html": "<p>Opis produktu…</p>",
"images": [
"https://dropshippers.pl/uploads_products/prod_123.jpg",
"https://dropshippers.pl/uploads_materials/123/abc.jpg"
],
"price": 24.5,
"availability": "available",
"active": true,
"updated_at": "2026-10-16T08:12:40Z"
}
],
"limit": 100, "total": 240, "has_more": true,
"next_cursor": "MjAyNi0xMC0xNiAwODoxMjo0MHwxMjM"
}
Synchronizacja zmian
Nie musisz co godzinę pobierać całego katalogu. Wystarczą dwa kroki:
- Pierwsze pobranie:
GET /products?limit=100, potem kolejne strony z parametremcursor, dopókihas_morejesttrue. Zapamiętaj najnowszeupdated_at, jakie dostałeś. - Kolejne razy, np. co 15 minut:
GET /products?updated_since=zapamiętany czas. Dostaniesz tylko produkty zmienione od tej chwili, też stronami z kursorem.
Produkt z "active": false wypadł z naszego katalogu. Wyłącz wtedy u siebie ofertę. Taki rekord zawiera tylko id, code, active i updated_at. Ten sam produkt może przyjść więcej niż raz, to normalne.
Plik XML i CSV
Jeśli Twój system wczytuje katalog z adresu pliku i nie potrafi wysłać klucza w nagłówku, użyj pliku XML albo CSV. Zawiera te same dane co API: cały katalog oraz produkty wycofane w ostatnich 30 dniach.
- Adres pliku tworzysz w panelu, w zakładce 🔌 API. Zawiera osobny token, inny niż klucz API. Pokazujemy go tylko raz, a unieważnisz go jednym kliknięciem.
- Token w adresie (
?token=) albo jako login i hasło w adresie:https://feed:TOKEN@dropshippers.pl/api/v1/feed.xml. Druga forma nie zostawia tokenu w logach po drodze, użyj jej, jeśli Twój system ją obsługuje. - Odświeżanie: plik generujemy co 15 minut. Można go pobrać do 12 razy na godzinę, w praktyce wystarczy raz na godzinę.
| Adres | Format |
|---|---|
| GET /feed.xml | XML w UTF-8. Jeden element <product id="…"> na produkt. |
| GET /feed.csv | CSV w UTF-8, separator średnik, pierwszy wiersz to nagłówki, teksty w cudzysłowach. Zdjęcia w kolumnach image_1, image_2 i kolejnych. |
<products generated_at="2026-10-16T08:00:00Z" count="240">
<product id="123">
<code>DS-123</code>
<active>1</active>
<name><![CDATA[Torebka damska]]></name>
<price>24.50</price>
<quantity>10</quantity>
<availability>available</availability>
<description><![CDATA[<p>Opis produktu…</p>]]></description>
<description_text><![CDATA[Opis produktu…]]></description_text>
<images>
<image>https://dropshippers.pl/uploads_products/prod_123.jpg</image>
</images>
<updated_at>2026-10-16T08:12:40Z</updated_at>
</product>
<product id="98">
<code>DS-98</code>
<active>0</active>
<quantity>0</quantity>
<updated_at>2026-10-16T09:01:05Z</updated_at>
</product>
</products>
quantity nie jest stanem magazynu. Dla produktu dostępnego podajemy stałą wartość, dla niedostępnego i wycofanego 0. Dzięki temu Twój system sam wstrzyma ofertę, gdy produktu zabraknie. Cena i ilość są puste do 10 opłaconych zamówień, tak jak w API.
Pola produktu
| Pole | Opis |
|---|---|
| id | ID produktu w dropshippers.pl. Nie zmienia się. |
| code | Stały kod produktu w API (DS- i ID). Służy do łączenia z Twoim systemem. W swoich ofertach nadajesz własne oznaczenia. |
| name | Nazwa produktu. Może mieć wartość null, gdy produkt nie ma jeszcze nazwy handlowej. Wtedy nazwij ofertę sam. |
| description_text | Opis do oferty jako zwykły tekst. Może mieć wartość null. |
| description_html | Ten sam opis w prostym HTML (akapity, listy, pogrubienia). Może mieć wartość null. |
| images | Pełne adresy zdjęć. Pierwsze to zdjęcie główne, dalej galeria. Pobierz je do siebie, zamiast linkować do nas z ofert. |
| price | Twoja cena zakupu u nas za sztukę, w złotych brutto. Ta sama, którą zapłacisz, składając zamówienie w panelu. Pojawia się po 10 opłaconych zamówieniach, wcześniej null. |
| availability | available (jest) albo out_of_stock (brak). Odświeżane mniej więcej co 45 minut. Po 10 opłaconych zamówieniach, wcześniej null. |
| active | true: produkt jest w katalogu. false (tylko przy updated_since): produkt wycofany. |
| updated_at | Czas ostatniej zmiany któregokolwiek z powyższych pól, w UTC. |
Limity
- 60 zapytań na minutę i 5000 na dobę na jeden klucz.
- 120 zapytań na minutę z jednego adresu IP.
- Maksymalnie 100 produktów na stronie.
Ile zapytań zostało w bieżącej minucie, pokazuje nagłówek odpowiedzi RateLimit-Remaining. Pełne pobranie katalogu to kilka zapytań, więc synchronizacja co 15 minut mieści się w limitach z dużym zapasem.
Kody błędów
Błąd zwracamy jako JSON z jednym polem: {"error": "opis"}.
| Kod | Znaczenie |
|---|---|
| 400 | Zły parametr: updated_since, cursor albo code. |
| 401 | Brak klucza albo klucz nieprawidłowy lub unieważniony. |
| 403 | API nieaktywne dla konta: przed 10 opłaconymi zamówieniami albo wyłączone przez nas. |
| 404 | Nie ma takiego produktu w katalogu albo nieznany adres. |
| 429 | Przekroczony limit zapytań. Odczekaj chwilę i spróbuj ponownie. |
| 500 | Błąd po naszej stronie. Spróbuj za kilka minut. |
Przykład w JavaScript (Node.js 18+)
Pełne pobranie katalogu ze stronicowaniem kursorem:
const KEY = process.env.DROPSHIPPERS_API_KEY; // klucz trzymaj w zmiennej środowiskowej
const BASE = 'https://dropshippers.pl/api/v1/products?limit=100';
async function fetchAll(since) {
const all = [];
let cursor = null;
do {
let url = BASE;
if (since) url += '&updated_since=' + encodeURIComponent(since);
if (cursor) url += '&cursor=' + cursor;
const res = await fetch(url, { headers: { 'X-API-Key': KEY } });
if (!res.ok) throw new Error('API: ' + res.status);
const page = await res.json();
all.push(...page.data);
cursor = page.next_cursor;
} while (cursor);
return all;
}
fetchAll().then(products => console.log(products.length, 'produktów'));
Zamówienia przez API
Twój system może sam zakładać u nas paczki: wysyła etykietę PDF, produkty i swój numer zamówienia. Zamawianie przez API włączamy ręcznie, napisz do nas na czacie w panelu. Używasz tego samego klucza API.
- Twój system wysyła zamówienie (
POST /orders). Paczka trafia do koszyka w panelu, w dzwonku 🔔. - Płacisz raz za wybrane paczki jedną płatnością PayU, kiedy chcesz. Dopiero opłacona paczka idzie do pakowania.
- Przypominamy o nieopłaconych paczkach po 24 i 48 godzinach. Po 72 godzinach bez płatności paczkę anulujemy.
- Status i numer przesyłki pobierasz przez
GET /orders.
| Metoda i adres | Co robi |
|---|---|
| POST /orders | Zakłada paczkę. multipart/form-data: label (PDF, do 5 MB i 10 stron), items (JSON), external_id (Twój numer zamówienia, od 1 do 64 znaków), notes (opcjonalnie). |
| GET /orders | Zamówienia złożone przez API. Parametry: updated_since, cursor, limit (max 100), external_id. |
| GET /orders/{id} | Jedno zamówienie. |
| POST /orders/{id}/cancel | Anuluje zamówienie, jeśli nie jest jeszcze pakowane. |
curl -H "X-API-Key: dsk_twój_klucz" \
-F "label=@etykieta.pdf;type=application/pdf" \
-F 'items=[{"code":"DS-123","quantity":2},{"product_id":456,"quantity":1}]' \
-F "external_id=ZAM-100234" \
"https://dropshippers.pl/api/v1/orders"
{
"data": {
"id": 5120,
"external_id": "ZAM-100234",
"status": "awaiting_payment",
"cancel_reason": null,
"total": 73.5,
"items": [
{ "product_id": 123, "code": "DS-123", "quantity": 2, "unit_price": 24.5 },
{ "product_id": 456, "code": "DS-456", "quantity": 1, "unit_price": 24.5 }
],
"tracking_number": "620000000000000000000000",
"tracking_courier": "inpost",
"label_check": false,
"created_at": "2026-10-20T08:12:40Z",
"updated_at": "2026-10-20T08:12:40Z"
}
}
- Produkty:
itemsto lista{"product_id": 123, "quantity": 2}albo{"code": "DS-123", "quantity": 2}. Do 10 różnych produktów w jednej paczce, ilość od 1 do 999. Ten sam produkt podany dwa razy sumujemy. - Cena: liczymy ją u nas, tak samo jak w panelu: Twoja cena zakupu w chwili przyjęcia zamówienia.
- Ten sam
external_iddrugi raz: nie zakładamy nowej paczki, tylko oddajemy istniejącą (kod 200, pole"idempotent": true). Bezpieczne przy ponawianiu po błędzie sieci. - Etykieta: numer przesyłki odczytujemy z PDF. Jeśli go nie rozpoznamy, przyjmujemy paczkę z
"label_check": truei sprawdzamy etykietę ręcznie. Ta sama etykieta (ten sam plik albo numer przesyłki) w ciągu 30 dni daje błąd 409. - Limity: 200 zamówień i 20 000 zł na dobę, do tego limity zapytań klucza.
created_atpo zapłacie pokazuje chwilę przyjęcia paczki do realizacji.
| Status | Znaczenie |
|---|---|
| awaiting_payment | Paczka czeka w koszyku na Twoją płatność. |
| accepted | Opłacona, czeka na pakowanie. |
| packing | Właśnie ją pakujemy. |
| packed | Spakowana, czeka na kuriera. |
| shipped | Nadana. |
| delivered | Doręczona. |
| problem | Coś wymaga wyjaśnienia, napiszemy na czacie. |
| cancelled | Anulowana. cancel_reason: payment_timeout (72 godziny bez płatności) albo cancelled. |
Anulowanie przez POST /orders/{id}/cancel: paczkę nieopłaconą anulujemy od razu; opłaconą, dopóki jej nie pakujemy, a pieniądze wracają na Twoje saldo w panelu. Paczki w trakcie pakowania i później anulować się nie da (kod 409).
Błędy zamówień: 400 zły formularz, produkt albo PDF, 403 zamawianie wyłączone albo brak danych do faktury, 409 powtórzona etykieta albo płatność w toku, 429 limit dzienny.
Załóż konto i zacznij od pierwszych zamówień
Konto działa od razu po rejestracji. API katalogu włącza się po 10 opłaconych zamówieniach.