API aplikacji pracownika
Logowanie pracownika z weryfikacją dwuetapową, sekcje aplikacji, Moja praca (grafik, zamiany zmian, deklaracje dostępności), dokumenty magazynowe z korektą i stornem oraz spis z natury w API aplikacji pracownika.
Zaktualizowano 2 listopada 2026
Na tej stronie
- Zanim zaczniesz
- Logowanie i token
- Sekcje aplikacji i uprawnienia
- Moja praca
- Grafik i wezwania do pracy
- Prośba o zamianę albo przejęcie zmiany
- Deklaracja dostępności
- Skanowanie kodu i produkty
- Dokument magazynowy krok po kroku
- Korekta, storno, kopia i wydruk
- Spis z natury
- Listy, limity i parametry
- Zmiany niezgodne wstecz w 1.3 i 1.4
- Powiązane
API aplikacji pracownika (/api/employee-app/v1, wersja 1.4) obsługuje aplikację mobilną personelu.
Pracownik loguje się swoim kontem z panelu i może tam sprawdzić grafik, oddać albo zamienić zmianę, wypełnić
deklarację dostępności, a na kolektorze ze skanerem prowadzić dokumenty magazynowe i spis z natury. API woła
te same usługi co panel, więc reguły, komunikaty i blokady (np. zamknięty okres magazynowy) są wspólne.
Pola i przykłady każdej operacji są w dokumentacji referencyjnej employee-app.yaml, w panelu pod
/help/api/employee-app (gdzie ją znaleźć).
Ten przewodnik opisuje przebiegi; przykłady są skrócone.
Zanim zaczniesz
- Pracownik potrzebuje aktywnego konta z dostępem do panelu. Konto bez dostępu (np. klient portalu albo
pracownik po zakończeniu zatrudnienia bez grup uprawnień) dostaje
403 NO_PANEL_ACCESS, konto wyłączone -403 USER_INACTIVE. Oba warunki API sprawdza przy każdym żądaniu, nie tylko przy logowaniu. - Uprawnienia to te same kody co w panelu. Najważniejsze dla aplikacji:
Logowanie i token
- Wyślij
POST /auth/loginzemail,passwordi opcjonalniedevice_name(np. „Zebra TC21 - magazyn 1”). - Gdy odpowiedź to
401 TWO_FACTOR_CODE_REQUIRED, konto ma weryfikację dwuetapową. Pokaż pole kodu i wyślij to samo żądanie jeszcze raz z hasłem icode(6 cyfr z aplikacji uwierzytelniającej) alborecovery_code(kod odzyskiwania z panelu). - Zapisz
tokenz odpowiedzi i dołączaj go do każdego żądania:Authorization: Bearer <token>. - Pobierz
GET /me- dane konta, kody uprawnień (permissions) i sekcje aplikacji (features). - Pobierz
GET /me/employees- zatrudnienia, jedno na lokalizację, aktywne najpierw. - Przy wylogowaniu wyślij
POST /auth/logout- przestaje działać tylko token z tego urządzenia.
POST /auth/login
{ "email": "jan.kowalski@example.com", "password": "...", "code": "123456", "device_name": "Zebra TC21 - magazyn 1" }
200 { "success": true, "data": { "token": "12|Xk3...", "token_type": "Bearer", "expires_at": "2026-12-01T10:00:00+01:00", "user": { ... } } }Nieznany e-mail i złe hasło dają ten sam błąd 422 VALIDATION_ERROR na polu email, więc API nie zdradza,
które konta istnieją. Status konta i weryfikację dwuetapową API sprawdza dopiero po poprawnym haśle.
| Odpowiedź | Co znaczy | Co zrobić |
|---|---|---|
401 TWO_FACTOR_CODE_REQUIRED |
konto ma włączone 2FA, a żądanie nie ma kodu | poproś o kod i ponów logowanie |
401 INVALID_TWO_FACTOR_CODE |
zły kod 2FA | poproś o kod jeszcze raz |
429 TOO_MANY_ATTEMPTS |
5 złych kodów w minutę na konto | odczekaj czas z komunikatu |
403 TWO_FACTOR_SETUP_REQUIRED |
grupa uprawnień wymaga 2FA, a konto go nie skonfigurowało | pracownik włącza 2FA w panelu (Ustawienia › Weryfikacja dwuetapowa) |
429 HTTP_ERROR |
ponad 5 prób logowania w minutę na parę e-mail + IP | odczekaj czas z nagłówka Retry-After |
Kod odzyskiwania działa raz. System wymienia zużyty kod na nowy, a nowy komplet pracownik widzi w panelu.
403 TWO_FACTOR_SETUP_REQUIRED dostaje też każde żądanie z tokenem wydanym wcześniej, gdy grupa uprawnień
nałożyła wymóg 2FA później.
Token działa tylko w tym API (zdolność employee-app); token aplikacji klienta dostaje 403 INVALID_TOKEN_TYPE.
Token wygasa po 30 dniach bez użycia (expires_at), a każde użycie przesuwa termin. Zmiana albo reset hasła
w panelu unieważnia wszystkie tokeny konta. W obu przypadkach kolejne żądanie dostaje 401 UNAUTHENTICATED
i pracownik loguje się ponownie.
Sekcje aplikacji i uprawnienia
GET /me → features mówi, które sekcje pokazać. Uprawnienia przelicza się z aktywnych grup uprawnień
(pamięć podręczna 5 minut).
features |
Kiedy true |
|---|---|
catalog |
products.index albo products.show |
warehouses |
warehouses.index |
warehouse_documents |
warehouse_documents.index |
inventory_counts |
inventory_counts.index |
my_schedule, swap_requests, availability_declarations |
konto ma aktywne zatrudnienie (GET /me/employees, is_active: true) |
full_schedule |
aktywne zatrudnienie i uprawnienie my_schedule.full_view |
| Obszar | Uprawnienia |
|---|---|
| Skan i produkty | products.index, products.show |
| Ceny | price_lists.show |
| Kontrahenci | contractors.index, contractors.show |
| Magazyny, stany, księga ruchów | warehouses.index, warehouses.show |
| Dokumenty magazynowe | warehouse_documents.index, show, create, edit, delete, confirm, cancel |
| Korekta i storno dokumentu | warehouse_documents.correct, warehouse_documents.reverse |
| Przesunięcie międzyoperatorskie (PMO) | dodatkowo warehouse_documents.inter_operator (utworzenie, zatwierdzenie, storno, kopia) |
| Spis z natury | inventory_counts.index, show, create, edit (liczenie), confirm, cancel |
| Wartości FIFO na wydruku dokumentu | warehouse_reports.values |
| Moja praca | bez uprawnień - wystarczy aktywne zatrudnienie |
| Pełny grafik ze współpracownikami | my_schedule.full_view |
| Stan księgowy i różnice spisu na ślepo w toku | inventory_counts.confirm |
Brak uprawnienia daje 403 FORBIDDEN z polem error.required_permission. Uprawnienie nadaje administrator
w panelu, w grupach uprawnień. Dokumenty, stany i spisy obejmują magazyny wszystkich operatorów, tak jak panel.
Moja praca
„Moja praca” pokazuje wyłącznie dane z aktywnych zatrudnień konta. Cudzy grafik, wpis, prośba albo deklaracja
dają 404 NOT_FOUND, a localization_uuid spoza zatrudnień - 404 LOCALIZATION_NOT_FOUND.
Grafik i wezwania do pracy
GET /me/schedule- moje zmiany ze wszystkich aktywnych zatrudnień, po dniu i godzinie. Zakresdate_from-date_todomyślnie dziś + 13 dni, najwyżej 62 dni (dłuższy daje422). Filtry:source,localization_uuid.GET /me/schedules- opublikowane grafiki lokalizacji, w których pracuję, z liczbą moich wpisów i minut.GET /me/schedules/{uuid}- moje wpisy w jednym grafiku, podsumowanie i liczba oczekujących próśb do mnie.GET /me/schedules/{uuid}/full- pełny grafik: zmiany wszystkich pracowników, filtryemployee_group_uuidisearch. Wymagamy_schedule.full_view.
Wpis grafiku (source: schedule) widać tylko z grafiku opublikowanego i w oknie widoczności: od daty
„Widoczny od” (bez niej - od razu) do daty „Widoczny do”. Wezwanie do pracy spod rezerwacji
(source: reservation) widać zawsze, póki wiąże - także poza grafikiem (schedule: null) i w grafiku jeszcze
nieopublikowanym. Wezwanie spod zamówienia wstępnego ma valid_until i is_preliminary: true; znika po upływie
ważności albo od razu po anulowaniu zamówienia. Pole work_call niesie okno pracy, nazwę pozycji i numer
zamówienia, bez danych klienta.
W pełnym grafiku dane współpracowników są minimalne: nazwa, grupy pracownicze i godziny zmian, bez kontaktów,
kart i PIN-ów. Pole is_me oznacza wiersz zalogowanego pracownika.
Prośba o zamianę albo przejęcie zmiany
- Wybierz swoją zmianę z
can_swap: true(zGET /me/schedulealbo z grafiku). - Pobierz
GET /me/schedule-entries/{entry}/swap-targets- współpracowników tej samej grupy w lokalizacji.can_takeovermówi, czy przejmą zmianę bez kolizji z własną. - Przy zamianie pobierz
GET /me/schedule-entries/{entry}/swap-targets/{employee}/entries- zmiany współpracownika do wymiany (can_swap- bez kolizji po obu stronach). - Wyślij
POST /me/swap-requestszoffered_entry_uuid,target_employee_uuidi opcjonalniemessage. Zrequested_entry_uuidto zamiana, bez niego - przejęcie zmiany. - Adresat widzi prośbę w
GET /me/swap-requests(direction: incoming) i wysyłaPOST .../acceptalboPOST .../reject. Autor może wycofać oczekującą prośbę przezPOST .../cancel.
Po akceptacji zamiana wykonuje się od razu, bez zgody kierownika, a inne oczekujące prośby dotyczące tych
zmian system anuluje. Prośba wygasa z końcem dnia przed zmianą. Odmowa reguł zamiany (zmiana przeszła, grafik
nieopublikowany, kolizja godzin, inna oczekująca prośba) daje 409 SWAP_NOT_ALLOWED z powodami
w error.errors. Prośba, która nie jest już oczekująca albo wygasła, daje 409 SWAP_NOT_PENDING.
Wysyłanie próśb ma limit 30 żądań na minutę.
Deklaracja dostępności
- Pobierz
GET /me/availability-declarations(filtrstate).state=open(można wypełniać),upcoming(przed terminem) alboclosed(po terminie);filled_days/total_days- postęp. - Otwórz
GET /me/availability-declarations/{uuid}- każdy dzień okresu z moim wpisem (entry,null= niewypełniony) i godzinami pracy z opublikowanego grafiku (scheduled_work). - Zapisz dzień:
PUT /me/availability-declarations/{uuid}/days/{YYYY-MM-DD}ztypei opcjonalnietime_slotsorazpreferred_group_uuid.
PUT /me/availability-declarations/{uuid}/days/2026-12-01
{ "type": "available", "preferred_group_uuid": "1b2c...", "time_slots": [ { "start_time": "08:00", "end_time": "12:00" }, { "start_time": "14:00", "end_time": "20:00" } ] }type:available(Dostępny),vacationalbooff. PrzyvacationioffAPI pomija przedziały.availablebeztime_slotsznaczy „dostępny cały dzień” - tak samo czyta go przydział pracowników do rezerwacji i sprawdzanie kolizji z grafikiem.- Przedziały (do 10) muszą kończyć się po początku i nie mogą na siebie nachodzić - inaczej
422na polutime_slots. Dzień spoza okresu deklaracji daje422na poludate. preferred_group_uuidprzyjmuje tylko jedną z aktywnych grup pracownika (listaemployee_groupsna karcie deklaracji). Inna grupa daje422na polupreferred_group_uuid, nieznany uuid -404.- Poza terminem wypełniania (przed
fill_fromalbo pofill_until) zapis daje409 DECLARATION_CLOSED. - W dniu ze zmianą w opublikowanym grafiku
vacation,offalbo przedziały nieobejmujące zmiany dają409 SCHEDULE_CONFLICTz listą kolizji werror.errors. Deklaracja nie może odebrać godzin z grafiku.
Każda zmiana trafia do historii deklaracji, tak jak zapis w panelu.
Skanowanie kodu i produkty
GET barcode/{code} to główne wejście skanera. Szuka aktywnego produktu po kolei: po kodzie kreskowym
artykułu albo SKU, po kodzie kreskowym opakowania zbiorczego, na końcu po kodzie produktu. Zwraca produkt,
stany we wszystkich magazynach i cenę z cenników lokalizacji. Produkt ma is_stock_item, is_package,
allows_fractional_quantity i units (jednostki dodatkowe z kodami EAN).
Cenę API liczy dla lokalizacji z parametru localization_uuid, a bez niego - dla domyślnej lokalizacji
użytkownika. Brak lokalizacji daje price: null, a nieznany localization_uuid - 404 LOCALIZATION_NOT_FOUND.
Dokument magazynowy krok po kroku
- Utwórz szkic:
POST warehouse-documentsztype(PZ, WZ, MM, RW albo PMO) iwarehouse_uuid. PZ i WZ wymagającontractor_uuid, MM i PMO -target_warehouse_uuidinnego niż magazyn źródłowy. - Dodawaj pozycje:
POST warehouse-documents/{uuid}/itemszbarcodealboproduct_uuidiquantity. Pozycję zmienisz przezPUT, usuniesz przezDELETE. - Sprawdź skutki:
GET warehouse-documents/{uuid}/stock-preview- stan obecny, zmiana i stan wynikowy pozycji. - Zatwierdź:
POST warehouse-documents/{uuid}/confirm. Numer w numeracji operatora (np.PZ/FIRM/001/2026) dokument dostaje dopiero teraz; szkic manumber: nullinumber_label„Szkic PZ”. - Gdy odpowiedź to
409 STOCK_WARNINGS, pokaż ostrzeżenia zerror.warningsi po akceptacji pracownika ponów zatwierdzenie zforce: true.
Reguła operatora obowiązuje już przy wystawieniu i przy zmianie nagłówka: MM tylko między magazynami tego
samego operatora, PMO tylko do magazynu innego operatora. Naruszenie daje 422 na polu
target_warehouse_uuid. Pozostałe warunki (pozycje, data, okres zamknięty, stan) sprawdza zatwierdzenie.
- Skan kodu opakowania zbiorczego ustawia jednostkę wprowadzenia (np. zgrzewka);
unit_uuidwskazuje ją wprost. accepts_price: false(WZ, RW, MM, INW i ich korekty): API pomija cenę towaru i zapisuje 0. Wartość rozchodu liczy wycena FIFO przy zatwierdzeniu. Opakowanie zwrotne ma zawsze cenę równą kaucji.- PZ, WZ, MM i PMO same dokładają podpozycje opakowań przypisanych do artykułu (
line_kind: package,parent_item_uuid). - Flagi
can_edit,can_delete,can_confirm,can_cancel,can_correct,can_duplicate(orazcan_reversena karcie dokumentu) opisują stan dokumentu. Uprawnienia serwer sprawdza dopiero przy operacji - zestaw je zGET /me→permissions. - Anulować można tylko szkic (
POST .../cancel, powód 5-500 znaków). Zatwierdzony dokument cofa storno.
| Odpowiedź | Co znaczy | Co zrobić |
|---|---|---|
409 DOCUMENT_VALIDATION_FAILED |
dokumentu nie da się zatwierdzić; powody w error.errors (brak pozycji, data z przyszłości, zamknięty okres, brak towaru w magazynie bez ujemnych stanów) |
pokaż powody i pozwól poprawić dokument |
409 STOCK_WARNINGS |
zatwierdzenie da ujemny stan w magazynie, który na to pozwala | ponów z force: true po decyzji pracownika |
409 DOCUMENT_NOT_EDITABLE, DOCUMENT_NOT_DELETABLE, DOCUMENT_NOT_CANCELLABLE |
stan dokumentu nie pozwala na operację | odśwież dokument |
409 ITEM_NOT_ADDED, ITEM_NOT_UPDATED, ITEM_NOT_REMOVED |
odmowa operacji na pozycji; powód w message |
pokaż komunikat |
stock-preview i error.warnings wskazują pozycję i produkt przez item_uuid i product_uuid. Pola item_id
i product_id zostały tylko dla zgodności i są przestarzałe.
Korekta, storno, kopia i wydruk
| Operacja | Co robi | Odmowa |
|---|---|---|
POST warehouse-documents/{uuid}/correction |
szkic korekty zatwierdzonego dokumentu: PZ → PZK, WZ → WZK, RW → RWK, MM → MMK | 409 DOCUMENT_NOT_CORRECTABLE |
POST warehouse-documents/{uuid}/reverse |
storno: ruchy przeciwne do wszystkich ruchów dokumentu, status „Wystornowany” (reversed), numer zostaje; powód 5-500 znaków |
409 DOCUMENT_NOT_REVERSIBLE z powodami w error.errors |
POST warehouse-documents/{uuid}/duplicate |
nowy szkic tego samego rodzaju, magazynów i kontrahenta z dzisiejszą datą i pozycjami | 409 DOCUMENT_NOT_DUPLICABLE |
GET warehouse-documents/{uuid}/pdf |
ten sam wydruk co w panelu; inline=1 do podglądu; 30 żądań na minutę |
błędy w kopercie JSON |
Korektę prowadzi się tak: utwórz szkic korekty, zmień stan „po korekcie” każdej pozycji przez
PUT .../items/{item} (quantity = ilość po korekcie w jednostce ewidencyjnej, może być 0; price_net = cena
po korekcie), potem zatwierdź POST .../confirm. Do korekty nie dodaje się pozycji. Gdy z tego samego stanu
powstały dwa szkice korekty, drugi przy zatwierdzeniu dostaje DOCUMENT_VALIDATION_FAILED.
Nie koryguje się szkiców, dokumentów anulowanych i wystornowanych, INW ani PMO i dokumentów z PMO. PMO stornuje się w całości - razem z WZ i PZ, które z niego powstały. Korekty stornuje się od najnowszej. Storno nie wyprowadzi stanu poniżej zera w magazynie, który na to nie pozwala. Zasady opisują artykuły Dokumenty magazynowe i Korekty i storno.
Spis z natury
- Otwórz spis:
POST inventory-countszwarehouse_uuid,scopei opcjonalniesnapshot_at,is_blind,notes.scope:warehouse(pozycje ze stanem w magazynie),categories(wymagacategory_uuids) alboproducts(spis wyrywkowy - startuje pusty). - Licz skanami:
POST inventory-counts/{uuid}/entrieszbarcodealboproduct_uuidiquantity(domyślnie 1). Kod opakowania zbiorczego liczy się w jednostkach ewidencyjnych (2 zgrzewki po 6 szt. = 12 szt.). Towar spoza zakresu dostaje pozycję przy pierwszym wpisie. - Popraw pomyłkę:
PUT inventory-counts/{uuid}/lines/{line}zcounted_quantityzastępuje wpisy jedną ilością;nullprzywraca pozycję do niepoliczonych. - Sprawdzaj postęp:
GET inventory-counts/{uuid}(podsumowanie) iGET inventory-counts/{uuid}/lines(filtrfilter:all,uncounted,differences). - Zatwierdź:
POST inventory-counts/{uuid}/confirm. Gdy zostały pozycje niepoliczone, podajuncounted_policy:zero(stan zerowy, czyli niedobór całości) albounchanged(zostają poza spisem).
Stan księgowy to suma ruchów do chwili odcięcia snapshot_at (domyślnie teraz), więc sprzedaż w trakcie
liczenia nie wpływa na wynik. Zatwierdzenie zapisuje stany i różnice, a różnice księguje dokumentem INW
z chwilą odcięcia (warehouse_document w odpowiedzi; bez różnic dokument nie powstaje). Bez uncounted_policy
przy pozycjach niepoliczonych zatwierdzenie daje 422. Spis w toku można anulować (POST .../cancel, powód
5-500 znaków) - bez skutków w ewidencji.
Spis na ślepo (is_blind: true): do zatwierdzenia osoby liczące bez inventory_counts.confirm nie widzą
stanu księgowego ani różnic. Wtedy book_quantity i difference = null, w podsumowaniu differences,
shortage i surplus = null, a filter=differences daje 409 BLIND_COUNT. Karta spisu ma book_revealed
- czy to konto widzi stan księgowy. Po zatwierdzeniu wszystko jest jawne.
Odmowa usługi spisu daje 409 INVENTORY_COUNT_REFUSED: chwila odcięcia z przyszłości albo w zamkniętym okresie
magazynowym, nieznany kod, produkt spoza ewidencji magazynowej, ilość ułamkowa artykułu niepodzielnego, spis
już zamknięty. Wartości różnic (FIFO) API nie zwraca. Zasady spisu: Inwentaryzacja.
Listy, limity i parametry
Listy są stronicowane: page i per_page (1-100, domyślnie 25; GET /me/schedule - domyślnie 50), wynik
w data.items i data.pagination. Zasoby wskazuje się przez uuid. Parametr ścieżki, który nie jest uuid, daje
404 przed wykonaniem operacji. search ma najwyżej 100 znaków. Nieznany warehouse_uuid, operator_uuid,
contractor_uuid albo product_uuid w filtrach list daje 404 NOT_FOUND, a nie pustą listę.
Całe API ma limit 120 żądań na minutę, z własnym licznikiem, niezależnym od pozostałych interfejsów. Osobne limity mają
logowanie (5 na minutę na parę e-mail + IP), prośby o zamianę i wydruki PDF (po 30 na minutę). Przekroczenie
daje 429 HTTP_ERROR z nagłówkiem Retry-After. Nieoczekiwany błąd serwera daje 500 SERVER_ERROR w tej
samej kopercie. Pełna lista kodów: Kody błędów.
Zmiany niezgodne wstecz w 1.3 i 1.4
Aplikacja napisana dla wersji 1.1 albo 1.2 wymaga przeglądu w tych miejscach:
| Od | Zmiana | Co poprawić w aplikacji |
|---|---|---|
| 1.3 | POST warehouse-documents wymaga contractor_uuid dla PZ i WZ oraz target_warehouse_uuid dla MM i PMO, a regułę operatora (MM - ten sam, PMO - inny) sprawdza już przy wystawieniu |
pytaj o kontrahenta i magazyn docelowy przed utworzeniem szkicu; obsłuż 422 |
| 1.3 | powód anulowania ma 5-500 znaków | waliduj długość w formularzu |
| 1.3 | na dokumentach rozchodowych (accepts_price: false) cena towaru jest pomijana |
ukryj pole ceny przy tych dokumentach |
| 1.3 | nieznany warehouse_uuid albo product_uuid w filtrach listy dokumentów i księgi ruchów daje 404 zamiast pustej listy |
obsłuż 404 jako „nie znaleziono” |
| 1.3 | search najwyżej 100 znaków; parametry ścieżki muszą być uuid |
skróć pole wyszukiwania |
| 1.4 | preferred_group_uuid tylko spośród aktywnych grup pracownika; employee_groups karty deklaracji zawiera już tylko te grupy |
buduj listę wyboru z employee_groups |
W 1.4 zmieniło się też znaczenie dnia „Dostępny” bez godzin: to cały dzień także przy kolizjach z grafikiem,
więc taki zapis nie daje już 409 SCHEDULE_CONFLICT. Historia wszystkich wersji: Zmiany w API.
Powiązane
- Przegląd API i uwierzytelnianie Trzy interfejsy REST StayPark Suite - kto ich używa, jak się uwierzytelnić, jak wygląda koperta odpowiedzi, stronicowanie i limity żądań.
- Kody błędów API Zbiorcza lista kodów error.code trzech interfejsów API z kodem HTTP, znaczeniem i operacjami, które je zwracają.
- Wystawianie dokumentu magazynowego Jak przyjąć towar od dostawcy (PZ), wydać go (WZ, RW) albo przesunąć (MM, PMO) - wystawić dokument magazynowy, dodać pozycje i zatwierdzić go, żeby zaksięgować ruchy w stanach.