Fridsee — API sprzedawcy, wersja 1 POST https://api.fridsee.com/api/sellers/v1/receipts Content-Type: application/json Authorization: Bearer TWÓJ_KLUCZ Klucz utwórz w panelu /sprzedawcy/panel. Jest pokazywany tylko przy utworzeniu, ważny rok i możliwy do unieważnienia. Przechowuj go na serwerze integratora. Uprawnienie: przesyłanie paragonów wyłącznie do firmy właściciela klucza. Przykład (curl, sekret w zmiennej środowiskowej): curl https://api.fridsee.com/api/sellers/v1/receipts \ -H "Authorization: Bearer $FRIDSEE_SELLER_KEY" \ -H "Content-Type: application/json" --data-binary @api-example.json Struktura jest pokazana w api-example.json. Pola w fields i items są tekstami, również kwoty i ilości. Separatorem dziesiętnym jest kropka. Zera wiodące identyfikatorów i GTIN należy zachować. row: unikalna dodatnia liczba całkowita w paczce. API nie dopuszcza skip=true; pomijanie jest dostępne w panelu. Pola nagłówka (wymagane): receiptId — maks. 160 znaków, identyfikator unikalny w sklepie pomiędzy dniami i kasami (np. sklep-kasa-data-numer). Nie używaj samego dziennego numeru. storeId — maks. 100 znaków, stabilny identyfikator punktu sprzedaży. issuedAt — YYYY-MM-DD lub YYYY-MM-DDTHH:mm:ss+01:00 / YYYY-MM-DDTHH:mm:ssZ. Daty od roku 2000, maksymalnie dzień w przyszłości. Normalizacja do UTC. currency — PLN, EUR, USD, GBP, CZK, SEK, DKK, NOK lub CHF. total — suma brutto po rabatach, nieujemna, do 2 miejsc po kropce. Pozycje (items): name — wymagana nazwa produktu, maks. 250 znaków. quantity — dodatnia ilość, do 3 miejsc po kropce. unit — pcs (sztuki), kg, g, l, ml. lineTotal — wartość brutto całej pozycji po rabatach, nieujemna, do 2 miejsc. gtin — opcjonalny tekst 8/12/13/14 cyfr z poprawną cyfrą kontrolną. Kwoty i ilości maksymalnie 1000000. Suma lineTotal musi być równa total z tolerancją 0.01. Nieznane pola są odrzucane. Bez danych osobowych klienta. Limity: 4 MB żądania, 100 paragonów, 200 pozycji na paragon, 5000 pozycji na paczkę. Import pliku w panelu: 2 MB, UTF-8, do 16 poziomów zagnieżdżenia. Nie obsługujemy podpisanych kontenerów fiskalnych JWS jako surowych plików; format kasy należy dopasować lub przekształcić do opisanej struktury. Duplikaty: firma + storeId + receiptId. Po normalizacji identyczna treść jest pomijana. Inna treść pod tym samym kluczem powoduje 409. Dokumentów nie nadpisujemy. Ponowienie po utracie odpowiedzi jest bezpieczne: już zapisane paragony zostaną policzone jako duplicates. Kolejność pozycji jest istotna. Wszystkie błędy są sprawdzane przed zapisem. Błąd jednego paragonu blokuje całą paczkę. Równoległe zapisy w obrębie firmy są serializowane. 200: {added, duplicates, skipped, receiptIds}. receiptIds zawiera tylko nowo dodane dokumenty, duplicates liczy identyczne pominięte dokumenty. 400/422: błędna struktura lub dane; issues: [{row,field,message}]. 401: klucz błędny, wygasły lub unieważniony. 409: konflikt treści — popraw identyfikację dokumentu, nie zmieniaj jej tylko w celu obejścia rzeczywistego konfliktu. Żaden paragon z paczki nie zapisany. 413: żądanie za duże. 429: przekroczony limit; odczekaj przed ponowieniem. 5xx: awaria przejściowa; ponów z opóźnieniem, zachowując te same identyfikatory. Wersja 1 przyjmuje sprzedaż, nie korekty i zwroty z ujemnymi wartościami. Zapis w panelu sprzedawcy nie oznacza fiskalizacji ani weryfikacji podpisu. Odbiór paragonu przez klienta: POST /api/sellers/v1/receipts/{id}/share z tym samym kluczem API. Odpowiedź: {code, url, expiresUtc, message}. Link przekazuj wyłącznie właściwemu nabywcy, nie publikuj go ani nie zapisuj w logach. Link jest jednorazowy, ważny 24 godziny. Kolejne wywołanie przed odbiorem unieważnia poprzedni kod. Po odbiorze zwracany jest 409; nie można przekazać tego samego paragonu innemu klientowi. Po utracie odpowiedzi API i nieznanym id można wywołać: POST /api/sellers/v1/receipt-links {"storeId":"SKLEP01","receiptId":"..."}. Autoryzacja jak wyżej; wyszukiwanie dotyczy wyłącznie firmy klucza. Klient otwiera /paragony, loguje się na konto Fridsee, sprawdza sprzedawcę i wyraża zgodę dotyczącą tego jednego dokumentu. Następnie wybiera produkty, kategorie, miejsce przechowywania i terminy, po czym zatwierdza dodanie. Zgoda nie obejmuje przyszłych zakupów. Można ją wycofać przed dodaniem. Sprzedawca nie otrzymuje danych konta ani uprawnień do zapasów klienta. Ponowne zatwierdzenie nie tworzy kolejnych produktów. Niewybrane pozycje są pomijane; nie można potem dodać tego paragonu drugi raz. Zapasy synchronizowane zachowują istniejące wymaganie Premium gospodarstwa. STAŁE POŁĄCZENIE KONTA KLIENTA Z SIECIĄ 1. Zalogowany klient inicjuje połączenie w systemie sieci. Backend sieci wywołuje: POST /api/sellers/v1/customer-connections Authorization: Bearer TWÓJ_KLUCZ {"customerReference":"nieosobowy-stabilny-identyfikator-klienta"} Nie przesyłaj e-maila, telefonu, numeru karty ani hasła klienta. customerReference jest identyfikatorem wewnętrznym sieci (maks. 160 znaków). Fridsee zapisuje jego skrót; zakres unikalności to firma właściciela klucza API, obejmująca jej sklepy. Odpowiedź: {id, code, url, expiresUtc, consentVersion}. Sieć zapisuje id przy właściwym koncie klienta i przekazuje url wyłącznie temu zalogowanemu klientowi. Kod jest tajny, jednorazowy, ważny 15 minut. Nie logować kodu, pełnego linku ani nagłówka Authorization. Nie przekazywać linku przez ogólnodostępny kod QR. 2. Klient otwiera link we Fridsee, loguje się, sprawdza nazwę firmy i osobno zatwierdza zgodę na kolejne zakupy. Zgoda na pojedynczy paragon nie wystarcza. Sieć może sprawdzić status: GET /api/sellers/v1/customer-connections/{id} Odpowiedź: {id,status}, gdzie status = pending / active / expired / revoked. Nie zwracamy tożsamości, e-maila ani identyfikatora konta Fridsee. Aktywne powiązanie dla tego customerReference blokuje kolejne aktywacje (409). 3. Po statusie active sieć przesyła kolejne zakupy zwykłą metodą: POST /api/sellers/v1/receipts W korzeniu dotychczasowej paczki dodaje pole customerConnectionId = id. Przykład: /sellers/connected-api-example.json (id należy zastąpić prawdziwym). Cała paczka musi należeć do jednego klienta i jednego połączenia. Firma odpowiada za prawidłowe przypisanie transakcji do konta swojego klienta. Fridsee automatycznie tworzy prywatny podgląd. Nie trzeba wywoływać /share. EAN/GTIN służy do dopasowania aktywnych katalogów producentów. Nie jest wymagany. Odpowiedź 200 zachowuje dotychczasowe pola i dodaje delivered i deliveryDuplicates. delivered = liczba nowych podglądów; deliveryDuplicates = liczba już odebranych. receiptIds nadal zawiera wyłącznie nowo zapisane dokumenty sprzedawcy. 4. Klient może wyłączyć odbiór w /paragony → Połączone sieci i sklepy. Od chwili potwierdzenia wyłączenia nowe podglądy z tego połączenia nie powstaną. POST /receipts z tym id zwróci 409, code=connection_inactive; zatrzymaj wysyłkę. Nie usuwaj customerConnectionId i nie próbuj zastępować dostawy linkiem /share. Wznowienie wymaga nowego zaproszenia, nowego id i ponownej zgody klienta. Odebrane wcześniej paragony pozostają dostępne. Wyłączenie nie usuwa zapasów. TRWAŁOŚĆ I PONOWIENIA Zapis dokumentów sprzedawcy i zapis podglądów są dwiema transakcjami. Awaria pomiędzy nimi może pozostawić dokument sprzedawcy bez podglądu. Ponów tę samą paczkę z tym samym customerConnectionId, storeId i receiptId: treść nie zostanie powielona, a brakujący podgląd zostanie utworzony tylko przy nadal aktywnej zgodzie. Paczka podglądów zapisywana jest atomowo. Nie nadpisujemy ani nie przejmujemy paragonów odebranych przez inne konto; odrzuconych podglądów nie przywracamy. 409 code=receipt_already_claimed oznacza konflikt odbiorcy lub odrzucony dokument. 409 code=historical_receipt oznacza dokument zapisany przed aktywacją połączenia; nie wykonujemy automatycznego importu takich dokumentów wstecz. Wysyłanie bez customerConnectionId nadal działa jak wcześniej: zapis po stronie sprzedawcy, bez automatycznego przypisania do klienta.