REST API do integracji Twojego sklepu, ERP-a lub aplikacji z katalogiem Akces Dekoracje. Katalog z cenami i stanami, a dla kont z włączonymi zamówieniami — składanie i śledzenie zamówień. Uwierzytelnianie kluczem, format JSON. Stabilny kontrakt v1: nowe pola, kody błędów i wartości statusów mogą dochodzić, a zmiany niezgodne wstecz ogłaszamy mailowo z wyprzedzeniem (zasady zgodności i historia zmian).
W przeglądarce przetestujesz odczyt (katalog, statusy). Zamówienia i walidację wysyłasz tylko z serwera, z podpisem HMAC — zob. instrukcję zamówień.
Katalog produktów z cenami i stanami, zsynchronizowany z naszym systemem ERP, a dla kont z włączonymi zamówieniami — składanie i śledzenie zamówień. Format JSON.
SKU wariantu i rodzica, nazwa, kod kreskowy (EAN), ścieżka kategorii, kolor, pakowanie (karton zbiorczy / pudełko / opakowanie — liczba jednostek w każdym) i krok zamawiania (orderStep), jednostka, cena katalogowa netto oraz Twoja cena (yourPriceNetto, konta z zamówieniami), dostępny stan (zamaskowany), objętość kartonu zbiorczego, wszystkie zdjęcia wariantu (główne pierwsze), znacznik ostatniej zmiany (updatedAt). Filtrowanie po SKU wariantu, SKU rodzica, nazwie i dacie zmiany.
Każde żądanie jest uwierzytelniane kluczem. Dostęp może być ograniczony do uzgodnionych adresów IP. Dla kont z zamówieniami lista jest obowiązkowa i obejmuje wszystkie endpointy, także katalog. Zamówienia wymagają dodatkowo podpisu HMAC. Wszystkie żądania są rejestrowane. Stany magazynowe są maskowane.
Dla kont z włączonymi zamówieniami: walidacja próbna koszyka, złożenie zamówienia z podpisem HMAC, numer zamówienia w Akces i statusy realizacji. Obowiązują cena i dostępność Akces z chwili złożenia zamówienia. Pełna instrukcja →
Trzy kroki, żeby zacząć pobierać dane.
Skontaktuj się z nami pod adresem kontakt@akces.pl. Otrzymasz klucz w formacie pk_ + 32 znaki hex (np. pk_a1b2c3d4e5f6…) oraz parametry konta (limit żądań, lista dozwolonych adresów IP — obowiązkowa dla kont z zamówieniami).
Każde żądanie do /v1/* wymaga nagłówka X-Partner-Key. Bazowy URL: https://api.akces.pl.
# Pobierz pierwsze 5 produktów curl "https://api.akces.pl/v1/products?limit=5" \ -H "X-Partner-Key: pk_TWOJ_KLUCZ"
const res = await fetch( "https://api.akces.pl/v1/products?limit=5", { headers: { "X-Partner-Key": process.env.AKCES_API_KEY } } ); const { data, pagination } = await res.json(); console.log(`Mam ${pagination.total} produktów`);
// Wymagane: PHP 8+ z curl $ch = curl_init("https://api.akces.pl/v1/products?limit=5"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["X-Partner-Key: " . getenv("AKCES_API_KEY")], ]); $data = json_decode(curl_exec($ch), true); echo "Mam {$data['pagination']['total']} produktów\n";
import requests, os
r = requests.get(
"https://api.akces.pl/v1/products",
params={"limit": 5},
headers={"X-Partner-Key": os.environ["AKCES_API_KEY"]},
)
data = r.json()
print(f"Mam {data['pagination']['total']} produktów")Za pierwszym razem pobierz cały katalog (limit=200, kolejne strony). Potem dociągaj zmiany przez parametr updatedSince: podstaw pole timestamp z poprzedniej odpowiedzi minus 5 minut zapasu (odpowiedź może zawierać produkty bez zmian — przetwarzaj ją idempotentnie). updatedAt obejmuje zmiany danych produktu, stanów, cen katalogowych i zdjęć, ale nie Twojej ceny (yourPriceNetto — promocje, oferty, rabaty konta) ani rezerwacji, dlatego co 15–30 minut pobierz też pełną listę. Przed wysłaniem zamówienia sprawdź koszyk przez POST /v1/orders/validate.
# Zmiany od poprzedniego pobrania # (updatedSince = pole timestamp z poprzedniej odpowiedzi minus 5 min) curl "https://api.akces.pl/v1/products?updatedSince=2026-11-05T16:43:10Z&limit=200" \ -H "X-Partner-Key: pk_TWOJ_KLUCZ" # Co 15–30 min — pełna lista (kolejne strony: page=2, 3…) curl "https://api.akces.pl/v1/products?limit=200&page=1" \ -H "X-Partner-Key: pk_TWOJ_KLUCZ"
Pełny opis parametrów i schematów odpowiedzi znajdziesz w interaktywnej dokumentacji. Endpointy zamówień są dostępne dla kont z włączonymi zamówieniami — szczegóły niżej.
page, limit (maks. 200), sku, parentSku, search, updatedSince (data w formacie ISO 8601, inaczej 400).updatedSince, externalOrderNumber, page, limit.id z odpowiedzi POST).ok, degraded (katalog działa, zamówienia chwilowo niedostępne) albo error (HTTP 503). Bez uwierzytelniania — używaj do monitoringu (np. UptimeRobot, Pingdom).Pojedynczy produkt z /v1/products dla konta z włączonymi zamówieniami. Dane produktu są prawdziwe; cena, stan, ścieżka kategorii i data są przykładowe. Pola ean (kod kreskowy) i category (ścieżka kategorii) mogą być null, jeśli towar nie ma ich uzupełnionych. images zawiera wszystkie zdjęcia wariantu (główne pierwsze); imageUrl to zawsze pierwsze z nich, zachowane dla zgodności ze starszymi integracjami.
{
"sku": "A02-003",
"parentSku": "A02",
"name": "Róża pianka główka 2 cm (144 szt.)",
"ean": "5907489847698", // kod kreskowy (EAN) z karty towaru
"category": "Kwiaty sztuczne/Główki kwiatowe", // pełna ścieżka kategorii (tu przykładowa)
"colorName": "#003 red",
"packaging": { "outerCarton": 120, "innerCarton": null, "package": 1 }, // liczba jednostek w kartonie zbiorczym / pudełku / opakowaniu
"unit": "opak",
"priceNetto": 10.95, // cena katalogowa netto (przykładowa)
"yourPriceNetto": 7.67, // Twoja aktualna cena (tu: rabat konta 30%; tylko konta z włączonymi zamówieniami) — informacyjnie; w zamówieniu obowiązuje cena z chwili jego złożenia
"orderStep": 1, // ilość = wielokrotność tej liczby (najmniejsze opakowanie)
"minOrderQuantity": 5, // najmniejsza ilość do zamówienia (Główki kwiatowe: 5 opakowań; inne kategorie = orderStep)
"availableStock": 240, // zamaskowany (przykładowy): maks. 2 × outerCarton; maks. ilość do zamówienia
"cartonVolume": 0.106, // objętość kartonu zbiorczego, m³
"imageUrl": "https://b2b.akces.pl/api/images/A02/A02-003-01.jpg", // główne zdjęcie = images[0] (adres może mieć parametr ?v=…)
"images": [ // wszystkie zdjęcia, główne pierwsze
"https://b2b.akces.pl/api/images/A02/A02-003-01.jpg",
"https://b2b.akces.pl/api/images/A02/A02-003-02.jpg"
],
"updatedAt": "2026-09-25T14:30:00.000Z"
}
Zasady współpracy, bezpieczeństwo, podpis z wektorem testowym, reguły walidacji, statusy, ponawianie i lista kontrolna startu: api.akces.pl/docs/zamowienia.
Dla kont z włączonymi zamówieniami. Zamówienie trafia na konto Twojej firmy (przypisanej do klucza) i jest zawsze zakładane jako odbiór osobisty (Magazyn Akces, ul. Sławęcińska 3, 05-850 Macierzysz), płatne przelewem (termin według warunków Twojego konta), dokument: faktura, ceny netto. Adresu dostawy nie podaje się.
Sprawdzamy wszystkie reguły naraz i zwracamy pełną listę błędów. Jeden błąd odrzuca całe zamówienie — poprawne pozycje nie są zapisywane osobno.
GET /v1/products) i być dostępny w sprzedaży przez API; każdy SKU najwyżej raz w zamówieniu. Opcjonalny ean sprawdzamy krzyżowo z kartoteką.orderStep — liczby jednostek w najmniejszym zdefiniowanym opakowaniu (1 = bez ograniczeń). Np. opakowanie 5 szt., pudełko 20, karton 100 → możesz zamówić dowolną wielokrotność 5: 5, 10, 15, 20…, ale nie 9.minOrderQuantity. Dotyczy kategorii Kwiaty sztuczne / Główki kwiatowe: każdy kolor zamawiasz w ilości co najmniej 5 opakowań (minOrderQuantity = 5 × packaging.package), także produkty z pudełkiem — pudełko lub karton spełnia warunek, jeśli mieści co najmniej 5 opakowań. W pozostałych produktach minOrderQuantity = orderStep.availableStock w chwili złożenia zamówienia (wartość z wcześniej pobranego katalogu mogła się zmienić). Towar rezerwujemy w chwili złożenia zamówienia.unitPriceNetto jest opcjonalne i tylko informacyjne — nie porównujemy go z ceną Akces). Zastosowane ceny wracają w odpowiedzi. Zatwierdzenie przez Akces (PENDING_REVIEW → ACCEPTED) nie zmienia cen ani rezerwacji.PLN. Nieznane pola w JSON są błędem (chroni przed literówkami w nazwach pól).Oprócz X-Partner-Key każde żądanie POST (zamówienie i walidacja próbna) wymaga nagłówków:
X-Timestamp: 1790160000 // Unix, sekundy — okno ±300 s
X-Signature: sha256=<hex HMAC-SHA256(sekret, X-Timestamp + "." + ścieżka + "." + surowe_body)>
Sekret podpisu (whsec_…) przekazujemy osobnym kanałem. Ścieżka to /v1/orders albo /v1/orders/validate (podpis walidacji próbnej nie zadziała jako zamówienie). Podpisz dokładnie te bajty, które wysyłasz jako body. Wywołania tylko z serwera — żądania z przeglądarki (z nagłówkiem Origin) są odrzucane (403 BROWSER_NOT_ALLOWED). Wektor testowy do sprawdzenia Twojej implementacji znajdziesz w instrukcji zamówień.
Przykład wywołuje walidację próbną. Żeby złożyć prawdziwe zamówienie, zmień ścieżkę na /v1/orders w podpisie i w adresie — zamówienie trafi na produkcję i zarezerwuje towar.
import crypto from "node:crypto"; const body = JSON.stringify({ externalOrderNumber: "TEST-0001", currency: "PLN", notes: "Odbiór we wtorek", lines: [{ lineNo: 1, sku: "A02-003", quantity: 12 }], }); const ts = String(Math.floor(Date.now() / 1000)); const sig = crypto.createHmac("sha256", process.env.AKCES_SIGNING_SECRET) .update(ts + "./v1/orders/validate." + body).digest("hex"); const res = await fetch("https://api.akces.pl/v1/orders/validate", { method: "POST", headers: { "Content-Type": "application/json", "X-Partner-Key": process.env.AKCES_API_KEY, "X-Timestamp": ts, "X-Signature": "sha256=" + sig, }, body, }); const json = await res.json(); // 200 → json.data.valid, json.data.errors, json.data.lines (ceny Akces)
$body = json_encode([ "externalOrderNumber" => "TEST-0001", "currency" => "PLN", "lines" => [["lineNo" => 1, "sku" => "A02-003", "quantity" => 12]], ], JSON_UNESCAPED_UNICODE); $ts = (string) time(); $sig = hash_hmac("sha256", $ts . "./v1/orders/validate." . $body, getenv("AKCES_SIGNING_SECRET")); $ch = curl_init("https://api.akces.pl/v1/orders/validate"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, // dokładnie ten sam string, który podpisano CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "X-Partner-Key: " . getenv("AKCES_API_KEY"), "X-Timestamp: " . $ts, "X-Signature: sha256=" . $sig, ], ]); $result = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
import hashlib, hmac, json, os, time, requests
body = json.dumps({
"externalOrderNumber": "TEST-0001",
"currency": "PLN",
"lines": [{"lineNo": 1, "sku": "A02-003", "quantity": 12}],
}, ensure_ascii=False).encode("utf-8")
ts = str(int(time.time()))
sig = hmac.new(os.environ["AKCES_SIGNING_SECRET"].encode(), ts.encode() + b"./v1/orders/validate." + body, hashlib.sha256).hexdigest()
r = requests.post("https://api.akces.pl/v1/orders/validate", data=body, headers={
"Content-Type": "application/json",
"X-Partner-Key": os.environ["AKCES_API_KEY"],
"X-Timestamp": ts,
"X-Signature": "sha256=" + sig,
})201 — przyjęte (status: ACCEPTED), towar zarezerwowany. Numer referencyjny zamówienia w Akces (np. CX/0412/09/26) dostajesz od razu w akcesOrderNumber; numer zamówienia w systemie Akces (ZO, np. ZO/0123/09/26) pojawi się w erpOrderNumber po przekazaniu do realizacji.202 — poprawne, towar zarezerwowany, czeka na zatwierdzenie przez Akces (PENDING_REVIEW); numer referencyjny jest już w akcesOrderNumber. Wynik sprawdzisz w GET /v1/orders.422 — odrzucone (REJECTED); data.errors zawiera wszystkie błędy z numerem pozycji. Popraw i wyślij ponownie — możesz użyć tego samego numeru.200 — powtórzone żądanie (ten sam numer i ta sama treść) — dostajesz aktualny stan pierwotnego zamówienia (idempotentReplay: true), duplikat nie powstaje. Ceny informacyjne (unitPriceNetto, expectedTotalNetto) nie wchodzą do porównania treści.409 — numer użyty już w zamówieniu ACCEPTED lub PENDING_REVIEW, z inną treścią. Zmiany w takim zamówieniu — kontakt z działem obsługi klienta.5xx (500, 502, 503, 504) — chwilowa niedostępność. Ponów z tym samym externalOrderNumber i tą samą treścią (nowy znacznik czasu i podpis) — to bezpieczne. Przy 503 i 429 odczekaj co najmniej czas z nagłówka Retry-After.{
"error": "Order rejected. See errors for details.",
"code": "ORDER_REJECTED",
"data": {
"status": "REJECTED",
"errors": [
{ "code": "INSUFFICIENT_STOCK", "lineNo": 1, "sku": "A02-003",
"message": "Quantity of A02-003 exceeds the available quantity (availableStock).",
"details": { "maxOrderable": 240 } },
{ "code": "PACKAGING_MULTIPLE", "lineNo": 2, "sku": "B14-01",
"message": "Quantity 100 of B14-01 is not a multiple of the packaging unit (96).",
"details": { "orderStep": 96, "packaging": { "package": null, "innerCarton": 96, "outerCarton": 1152 },
"suggestedQuantities": [96, 192] } }
],
… // odpowiedź skrócona: data zawiera też id, externalOrderNumber, lines, totalNetto, createdAt, updatedAt
}
}
Kody błędów: UNKNOWN_SKU, EAN_MISMATCH, PRODUCT_NOT_AVAILABLE, DUPLICATE_LINE, PACKAGING_MULTIPLE, BELOW_MINIMUM_QUANTITY (z minOrderQuantity), INSUFFICIENT_STOCK (z maxOrderable), CONTRACTOR_BLOCKED. Pełna tabela kodów HTTP: /docs/zamowienia.
Limity: 10 zamówień/min, 30 walidacji/min, 60 odczytów statusu/min; maks. 500 prób zamówień w ciągu ostatnich 24 h (okno kroczące, przyjęte i odrzucone łącznie); maks. 500 pozycji i 256 KB na zamówienie.
Stany są maskowane: wartości poniżej 5 pokazujemy jako 0, a wartości powyżej 2× kartonu zbiorczego (outerCarton) — jako 2× karton zbiorczy. Dla produktów bez zdefiniowanego kartonu zbiorczego stan nie jest ograniczany do 2× karton. Dla kont z zamówieniami availableStock jest dodatkowo zaokrąglany w dół do wielokrotności orderStep (np. 10 przy kroku 6 → 6) i jest to maksymalna ilość, jaką możesz zamówić. Produkty, których nie można zamówić przez API, mają wtedy availableStock 0 i yourPriceNetto null. Dzięki temu widzisz realną dostępność towaru do zamówienia.
Katalog: 200 OK, 400 niepoprawny parametr zapytania (np. updatedSince w złym formacie), 401 brak klucza albo nieprawidłowy klucz, 403 adres IP spoza listy dozwolonych (FORBIDDEN) albo żądanie przez http:// zamiast https:// (HTTPS_REQUIRED), 404 zasób nie istnieje, 405 niedozwolona metoda HTTP (lista dozwolonych w nagłówku Allow), 429 przekroczony limit żądań (z nagłówkiem Retry-After), 5xx błąd po naszej stronie (503 z nagłówkiem Retry-After).
Zamówienia: 201 przyjęte, 202 czeka na zatwierdzenie, 200 powtórka, 400 błąd schematu, 409 numer użyty z inną treścią, 413 za duże body, 415 brak nagłówka Content-Type: application/json, 422 odrzucone; 403 także ORDERS_DISABLED (konto bez włączonych zamówień), BROWSER_NOT_ALLOWED (żądanie z przeglądarki) i HTTPS_REQUIRED (żądanie przez http://). Pełna tabela: /docs/zamowienia.
Treść odpowiedzi z błędem jest w formacie JSON i zawiera pole code — stały identyfikator błędu do obsługi w Twoim programie.
Limity liczymy na konto, osobno dla każdej grupy: katalog (GET /v1/products i /v1/products/{sku}) — wspólny limit, domyślnie 60 żądań/min; POST /v1/orders — 10/min; POST /v1/orders/validate — 30/min; GET /v1/orders i /v1/orders/{id} — 60/min. Do tego maks. 500 prób zamówień (przyjętych i odrzuconych 422) w oknie kroczącym 24 h oraz maks. 500 pozycji i 256 KB body na zamówienie. Do masowego pobierania używaj listy z limit=200. Jeśli limit katalogu to za mało dla Twoich potrzeb — daj znać, podniesiemy.
Po przekroczeniu dostajesz HTTP 429 (RATE_LIMITED albo DAILY_LIMIT_EXCEEDED) z nagłówkiem Retry-After — odczekaj wskazaną liczbę sekund i ponów (przy DAILY_LIMIT_EXCEEDED ta sama wartość jest w polu retryAfterSeconds). Po 30 nieudanych próbach uwierzytelnienia w ciągu minuty z jednego adresu IP wszystkie żądania z tego adresu dostają 429 do końca tej minuty.
Na razie nie. Polecamy odpytywanie: zmiany katalogu dociągaj przez updatedSince (pole timestamp z poprzedniej odpowiedzi minus 5 min), a co 15–30 min pobierz pełną listę (limit=200) — Twoja cena (yourPriceNetto) i rezerwacje zmieniają się bez zmiany updatedAt. Statusy zamówień sprawdzaj przez GET /v1/orders?updatedSince=…. Jeśli potrzebujesz powiadomień push do Twojego systemu — zgłoś się, rozważymy to w planach rozwoju.
Dla zamówień ACCEPTED pole fulfillmentStatus pokazuje etap realizacji: NOWE, DO_REALIZACJI, W_REALIZACJI, WSTRZYMANE, DO_ODBIORU, WYSLANE, ODEBRANE, CZESCIOWO_ZREALIZOWANE, ZREALIZOWANE albo ANULOWANE. Nieznaną wartość traktuj jak W_REALIZACJI. Dla zamówień PENDING_REVIEW, REJECTED i DECLINED pole ma wartość null. Szczegóły: /docs/zamowienia.
Nie udostępniamy gotowych SDK. Wygeneruj klienta z naszej specyfikacji /openapi.json, używając openapi-generator: dostępne są generatory dla Pythona, Javy, JS/TS, PHP, C#, Go, Rusta i wielu innych. Ponieważ w ramach v1 mogą dochodzić nowe pola i wartości, włącz opcje, które je tolerują: --additional-properties=disallowAdditionalPropertiesIfNotPresent=false,enumUnknownDefaultCase=true.
Napisz na kontakt@akces.pl. Wygenerujemy nowy klucz — stary przestanie działać w chwili przełączenia. Rotację klucza lub sekretu podpisu możesz zlecić planowo: umówimy godzinę przełączenia, a nowe dane przekażemy osobnymi kanałami.
Aktualnie dostępne jest tylko produkcyjne API. Odczyt katalogu jest bezpieczny do testowania na żywo — zacznij od ?limit=1. Zamówienia testuj przez POST /v1/orders/validate (te same reguły i ten sam algorytm podpisu ze ścieżką /v1/orders/validate; bez rezerwacji i bez zapisu). Walidacja próbna nie sprawdza, czy externalOrderNumber był już użyty (409 lub powtórka 200), ani limitu prób na 24 h.
Pytania, problemy, sugestie?
Zamówienia, zmiany, anulowanie, odbiór, większe ilości.
Błędy integracji, podniesienie limitu, nowy klucz lub sekret podpisu.
kontakt@akces.plKatalog w przeglądarce i składanie zamówień dla klientów z kontem B2B (wymaga logowania).
b2b.akces.pl →Aktualna wersja kontraktu: 1.5.1.
W ramach v1 możemy dodawać pola w odpowiedziach, kody błędów i wartości statusów — ignoruj nieznane pola, a nieznaną wartość obsłuż jako przypadek ogólny. Zmiany niezgodne wstecz ogłaszamy mailowo z wyprzedzeniem.
minOrderQuantity = 5 × packaging.package) obowiązuje wszystkie produkty, także z pudełkiem. Dla produktów z pudełkiem orderStep wraca do opakowania (wcześniej pudełko) — znów można zamawiać je w opakowaniach.minOrderQuantity w katalogu i kod błędu BELOW_MINIMUM_QUANTITY — minimalne ilości w kategorii Kwiaty sztuczne / Główki kwiatowe (produkty z pudełkiem: orderStep = pudełko; bez pudełka: minimum 5 opakowań).akcesOrderNumber (zmiana nazwy pola przed uruchomieniem zamówień).fulfillmentStatus.Retry-After także przy DAILY_LIMIT_EXCEEDED.unitPriceNetto i expectedTotalNetto przyjmują 0 i null.GET /v1 zwraca opis API./health sprawdza zależności usługi.updatedSince z niepoprawną datą zwraca 400.unitPriceNetto i expectedTotalNetto są opcjonalne; usunięte błędy rozbieżności ceny pozycji i wartości zamówienia.availableStock./v1/orders), pola yourPriceNetto i orderStep w katalogu.images[] — wszystkie zdjęcia wariantu.ean i category.