Przegląd
Grocey to API zapisu dla własnego konta zakupowego użytkownika. Jest teżkatalog, który możesz czytaćale to produkt uboczny, nie właściwy produkt:searchistoresodpowiadają dla sklepu, w którym dana osoba faktycznie robi zakupy,cartzapisuje do jej prawdziwego koszyka, a tam, gdzie dostawca to obsługuje,orderszwraca jej prawdziwą historię zamówień. Nic tutaj nie jest zeskrobane z zewnątrz ani pobrane z kanału partnera; Grocey prowadzi prawdziwą stronę dostawcy w izolowanej sesji przeglądarki, logując się dokładnie tak, jak zrobiłaby to ta osoba ręcznie.
Jeśli chcesz tylko połączyć swój sklep z Claude lub ChatGPT i nie piszesz kodu, ta strona nie jest dla Ciebie: przejdź zamiast tego do Grocey dla asystentów. Ta strona to techniczna dokumentacja referencyjna dla deweloperów. Grocey dla deweloperów to krótszy opis produktu i instrukcja konfiguracji, a Twój panel uruchamia prawdziwy proces łączenia na prawdziwym koncie, bez niczego do zainstalowania.
Dzisiaj Grocey działa produkcyjnie jako substrat pierwszej strony z jednym wywołującym: to on zasila konta sklepów spożywczych wewnątrz Alfredo, naszego własnego agenta concierge. Ta strona dokumentuje publiczną platformę dla deweloperów budowaną na tym substracie: Twój własny kluczgro_*, Twoje własne przekierowanie, podpisany webhook przy połączeniu użytkownika oraz ta sama płaszczyzna konta dostępna przez MCP.
Dwie płaszczyzny
Płaszczyzna dla deweloperów, zarównoapi.grocey.shop/v1/*iPOST /mcp, jest uwierzytelniana Twoimgro_*kluczem od początku do końca: nie ma tu żadnej anonimowej trasy, w tym katalogu dostawców. Strona łączenia dla użytkownika końcowego (link.grocey.shop/c) to inny sposób uwierzytelniania: podpisany, jednorazowy identyfikator linku, nigdy Twój klucz. Posiadanie linku daje użytkownikowi dostęp do jego własnego konta i żadnego innego.Grocey dla asystentówto ta sama płaszczyzna dla użytkownika końcowego, tylko ze stroną z przodu, dla kogoś, kto woli w ogóle nie czytać tej sekcji.
Uwierzytelnianie
Każde żądanie w warstwie deweloperskiej będzie zawieraćAuthorization: Bearer gro_live_…(lubgro_test_…na sandboksie). Klucz pokazujemy raz, przy tworzeniu, i trzymamy wyłącznie jako hash, dokładnie tak, jak reszta platformy Loki Labs robi to z kluczami API. To nie jest współdzielony sekret, którego identyczną kopię ma każdy programista.
# every developer-plane request curl https://api.grocey.shop/v1/providers?country=PL \ -H "Authorization: Bearer gro_live_…"
Linki łączące
Wygeneruj link z własnymredirect_url. Cel typuhttpsrejestrujesz w aplikacji z wyprzedzeniem; własnego schematu aplikacji, np.yourapp://returnjuż nie, bo wyniki wracają przez API i webhook, więc w przekierowaniu nie ma nic, co warto by wykraść. Tak czy inaczej adres odczytujemy z wywołania generującego link, nigdy ze strony, na którą trafia użytkownik. Dzięki temu link do połączenia nie zamienia się w open redirect akurat tam, gdzie miałoby to najgorsze skutki.
Użytkownik otwiera link, widzi, o co prosisz, wybiera dostawcę i loguje się. Przeglądarka wraca na twójredirect_urlzstatus, a twój pierwotnystate:
-
status=connected, zconnection_id. Udało się. -
status=cancelled. Użytkownik zamknął okno. Żaden webhook nie leci: nic nie zostało podjęte, więc nazwanie tego błędem byłoby nadużyciem. -
status=failed, i tylko wtedy, gdy użytkownik tak zdecyduje. Przy błędzie pokazujemy komunikat, a powrót jest zwykłym przyciskiem. Po błędzie nic nie przekierowuje automatycznie, bo to jedyny moment, w którym wyjaśnienie naprawdę się liczy.
Brak powrotu traktuj więc tak samo jakstatus=cancelled: przeglądarka, nad którą nie masz kontroli, może po prostu nigdy nie wrócić. To webhook mówi ci, że połączenie istnieje.
POST https://api.grocey.shop/v1/connect_links { "end_user_id": "usr_42", "redirect_url": "https://your-app.example/return", "state": "whatever-you-need-back", // optional, skips the provider picker "provider": "delio" } → { "connect_link_id": "cl_9f2k…", "url": "https://link.grocey.shop/c/…", "expires_at": "2026-09-10T12:00:00Z" }
Webhooki
Przekierowanie to udogodnienie UX, które użytkownik może porzucić; webhook to zapis zdarzenia. Każdy payload będzie podpisany:Grocey-Signature: t={timestamp},v1={hex}, HMAC-SHA256 z{timestamp}.{raw body}, czyli schemat Stripe, bo to właśnie do niego większość backendów ma już gotowy kod bibliotek. Dostarczanie jest co najmniej jednokrotne, więcevent_idto klucz idempotencji, a kolejność przy ponowieniach nie jest gwarantowana.
Piaskownica
Każdy kluczgro_test_trafia do jednego deterministycznego dostawcy testowego, więc pełną integrację zbudujesz i przetestujesz, zanim naprawdę obsłużymy potrzebny ci kraj. Dostawca sandbox jest w planach, jeszcze go nie ma. Nigdy nie pojawi się w poniższej tabeli pokrycia i nigdy nie zastąpi odpowiedzi na pytanie, czy prawdziwy dostawca działa.
Catalog API
Dwa endpointy odczytu na zindeksowanym katalogu, z tym samymgro_*kluczem co reszta. Nie są przypisane do połączenia ani do aplikacji, bo półka w sklepie wygląda tak samo dla wszystkich: co jedna aplikacja zindeksuje, czytają wszystkie.
providerjest wymagany.store_id,category_idiqzawężają wyniki,limitdomyślnie wynosi 50 i odrzuca wartości powyżej 200, a stronicowanie opiera się na kursorze, nie na offsecie, więc indeksowanie w połowie strony nie sprawi, że pominiesz produkt.
Ceny to jednostki podrzędne plus kod waluty, nigdy liczba zmiennoprzecinkowa, aprice_minortonulldla pozycji, której sklep nie wycenia na własnej liście. To prawdziwa odpowiedź, a nie brak danych: odczytanie jej jako zera wymyśliłoby darmowy produkt. Kategorie wracają z identyfikatorem dostawcy i liczbą produktów, anamejest na razie zawszenull: tylko wywołanie na żywo na zalogowanym koncie zna ludzką nazwę kategorii, a ten endpoint czyta z D1, nie ze sklepu.
Zasięg to dokładnie te sklepy, które Grocey indeksuje, wymienione poniżej. Sklep bez indeksacji zwraca pustą stronę, a nie błąd.
GET https://api.grocey.shop/v1/catalog/products?provider=delio&q=mleko&limit=2 → { "products": [ { "sku": "A0000709", "name": "Łaciate mleko UHT 2%", "price_minor": 399, "currency": "PLN", "available": true, "image_url": "https://images.prod.lait.app/…", "category_id": "3d2dedb1-0031-4223-aadb-65b1f256fa51", "description": null } ], // null on the last page "next_cursor": "eyJzIjoiZGVsaW8iLCJr…" } GET https://api.grocey.shop/v1/catalog/categories?provider=delio → { "categories": [ { "id": "3d2dedb1-0031-4223-aadb-65b1f256fa51", "name": null, "product_count": 1001 } ] }
Zasięg
To jedyna sekcja na tej stronie, która jest prawdziwa już teraz, a nie zapowiedzią: wygenerowana w czasie builda z dokładnie tych samych deklaracji dostawców, które czyta API.
Każdy dostawca poniżej ma też własną stronę, wygenerowaną z tych samych danych i podlinkowaną ze stopki: zobacz pełny indeks integracji, aby poznać hasła wyszukiwania i szczegóły logowania dla każdego sklepu.
Serwis click-and-collect Colruyt w Belgii i Luksemburgu. Zaloguj się e-mailem i hasłem z Collect&Go.
Polska dostawa artykułów spożywczych. Zaloguj się numerem telefonu i kodem SMS.
Polski internetowy supermarket z dostawą samochodem. Zaloguj się e-mailem i hasłem.
Ekspresowa dostawa zakupów od Żabki w Polsce. To samo konto i logowanie co w Delio.
Zakupy spożywcze i sklepy na Wolt. Zaloguj się linkiem, który Wolt wysyła na Twój adres e-mail.
Czego Grocey nie robi
Płatność jest domyślnie wyłączona, a oto co musiałoby być prawdą. grocery_checkoutto prawdziwe narzędzie w tym API, a nie zdanie doktryny obiecujące, że go nie ma. To, czy wywołanie kiedykolwiek się powiedzie, decydują cztery niezależne zabezpieczenia, wymuszane w kodzie, a nie w opisie narzędzia:
- Żaden podłączony dostawca tego nie implementuje. Delio,Frisco.pliWoltnie definiują żadnego
checkoutwięc wywołanie jest odrzucane, zanim cokolwiek innego się wydarzy. To zabezpieczenie, które działa już dziś. -
GROCEY_CHECKOUTmusi być ustawiona dokładnie na"enabled"we wdrożeniu. Domyślnie wyłączona, a włączyć ją może tylko właściciel. - Dana osoba musi już mieć zapisaną kartę płatniczą bezpośrednio u dostawcy. Grocey nigdy nie zbiera danych karty, więc konto bez zapisanej karty nie może zostać rozliczone, niezależnie od flagi.
- Token wygenerowany przez serwer, przypisany do dokładnej zawartości koszyka w chwili wyceny, musi wrócić niezmieniony. Model nie może go ani wygenerować, ani zmodyfikować, a weryfikacja przestaje działać w chwili, gdy koszyk się zmienia.
To nie jest obietnica z planu rozwoju, ani stwierdzenie "niedostępne, koniec tematu": mechanizm jest prawdziwy i już wdrożony. Brakuje dostawcy, który go implementuje, i przełącznika, który ktoś by włączył. Złożenie zamówienia pozostaje dotknięciem ekranu przez człowieka na stronie samego dostawcy, dopóki to się nie zmieni.
Bez ulubionych dań. Dostawca zwraca produkty identyfikowane własnym SKU, przypisanym do konkretnego sklepu; nic w tym kształcie nie jest daniem. Danie to wniosek wyciągnięty z zawartości koszyka, coś, co musielibyśmy wygenerować, a nie pobrać, a robienie tego za API, którego całą obietnicą jest "to naprawdę Twoje konto", to zły szew: zatarłoby granicę między tym, co naprawdę pochodzi z konta, a tym, co sami wymyśliliśmy.
Brak opublikowanego cennika. Koszt tutaj rośnie wraz z liczbą otwartych połączeń, a nie liczbą wywołań, a sufit współbieżności, który pozwoliłby ustalić rozsądną cenę, nie został jeszcze zmierzony. Liczba wybrana przed tym pomiarem byłaby zgadywanką z metką ceny.