[{"data":1,"prerenderedAt":3718},["ShallowReactive",2],{"pomoc:\u002Fpomoc\u002Fnarzedzia\u002Fwlasne-webhooki":3,"pomoc-pages:help_pl":3367},{"id":4,"title":5,"alt":6,"body":7,"description":3359,"extension":3360,"key":3361,"meta":3362,"navigation":1336,"order":1333,"path":3363,"seo":3364,"stem":3365,"__hash__":3366},"help_pl\u002Fpomoc\u002Fnarzedzia\u002Fwlasne-webhooki.md","Własne webhooki","\u002Fhelp\u002Ftools\u002Fcustom-webhook-tools",{"type":8,"value":9,"toc":3332},"minimark",[10,28,48,53,56,60,66,166,176,180,187,318,322,325,384,389,404,407,414,427,433,437,447,489,493,503,871,874,880,895,1016,1025,1036,1066,1070,1124,1130,1144,1148,1172,1271,1275,1294,3170,3174,3177,3184,3195,3211,3218,3223,3227,3248,3252,3308,3312,3328],[11,12,15],"callout",{"title":13,"type":14},"Funkcja eksperymentalna","warning",[16,17,18,19,23,24,27],"p",{},"Webhooki niestandardowe są we wdrożeniu kontrolowanym. Jeśli w\n",[20,21,22],"strong",{},"Ustawienia → Integracje"," nie widzisz karty ",[20,25,26],{},"Webhooki niestandardowe",", poproś swój kontakt w\nFibly o włączenie jej dla Twojego obszaru roboczego.",[16,29,30,32,33,38,39,43,44,47],{},[20,31,26],{}," pozwalają zamienić dowolne API HTTP, które już prowadzisz, w\nnarzędzie, którego bot użyje w trakcie rozmowy — sprawdzenie statusu zamówienia, wyszukanie\nklienta, otwarcie zgłoszenia w systemie wsparcia albo cokolwiek innego, co potrafi Twój backend\nprzez HTTP. W przeciwieństwie do gotowych integracji (",[34,35,37],"a",{"href":36},"\u002Fpomoc\u002Fnarzedzia\u002Fcalendly","Calendly",",\n",[34,40,42],{"href":41},"\u002Fpomoc\u002Fnarzedzia\u002Fprestashop","PrestaShop",") to samoobsługowy sposób podłączenia ",[20,45,46],{},"własnych","\nsystemów, bez udziału inżynierów Fibly — wymaga jednak dewelopera po Twojej stronie, który\nzbuduje odbierający endpoint i — w zakresie opisanym w tym przewodniku — zweryfikuje, że\nwywołanie rzeczywiście pochodzi od Fibly.",[49,50,52],"h2",{"id":51},"kiedy-jej-użyć","Kiedy jej użyć",[16,54,55],{},"Sięgnij po webhook niestandardowy, gdy chcesz, aby bot wywołał system, dla którego nie ma\ndedykowanej integracji Fibly: własne API zarządzania zamówieniami, wewnętrzny system zgłoszeń,\nbackend rezerwacji, CRM — cokolwiek dostępnego przez HTTPS. Jeśli dane lub akcja pasują już do\nistniejącej integracji (Calendly, PrestaShop), użyj jej zamiast tego — nie wymaga żadnego kodu po\nTwojej stronie.",[49,57,59],{"id":58},"budowanie-połączenia","Budowanie połączenia",[16,61,62,65],{},[20,63,64],{},"Połączenie"," to jedna z Twoich usług backendowych: jej adres bazowy i statyczne dane\nuwierzytelniające, których bot używa do jej wywoływania. Każde zdefiniowane narzędzie należy do\njakiegoś połączenia i wywołuje ścieżkę względem jego adresu bazowego.",[67,68,69,83,89,163],"ol",{},[70,71,72,73,75,76,78,79,82],"li",{},"Otwórz ",[20,74,22],{},", znajdź kartę ",[20,77,26],{}," i kliknij\n",[20,80,81],{},"Zarządzaj",".",[70,84,85,86,82],{},"Kliknij ",[20,87,88],{},"Dodaj połączenie",[70,90,91,92],{},"Uzupełnij:\n",[93,94,95,101,116,148],"ul",{},[70,96,97,100],{},[20,98,99],{},"Nazwa"," — etykieta na Twój własny użytek (np. „API sprawdzania zamówień\").",[70,102,103,106,107,111,112,115],{},[20,104,105],{},"Adres URL bazowy"," — główny adres Twojego API, np. ",[108,109,110],"code",{},"https:\u002F\u002Fapi.example.com",". Musi to być\npublicznie dostępny adres ",[20,113,114],{},"HTTPS"," — adresy lokalne lub prywatne oraz ruch nieszyfrowany\n(inny niż HTTPS) są odrzucane.",[70,117,118,121,122],{},[20,119,120],{},"Uwierzytelnianie"," — sposób, w jaki Fibly uwierzytelnia się w Twoim API:\n",[93,123,124,130,139],{},[70,125,126,129],{},[20,127,128],{},"Brak uwierzytelniania"," — żadne dane nie są wysyłane.",[70,131,132,135,136,82],{},[20,133,134],{},"Basic auth"," — nazwa użytkownika i hasło, wysyłane jako nagłówek ",[108,137,138],{},"Authorization: Basic",[70,140,141,144,145,82],{},[20,142,143],{},"Token typu Bearer"," — pojedynczy token, wysyłany jako ",[108,146,147],{},"Authorization: Bearer \u003Ctoken>",[70,149,150,153,154,157,158,162],{},[20,151,152],{},"Wysyłaj token weryfikacyjny"," — domyślnie wyłączone. Włącz to ustawienie, jeśli chcesz, aby\nFibly wysyłało podpisany nagłówek ",[108,155,156],{},"X-Fibly-Verification"," przy każdym wywołaniu na tym\npołączeniu (zobacz ",[34,159,161],{"href":160},"#weryfikacja-wywolujacego-x-fibly-verification","Weryfikacja wywołującego","\nponiżej). Gdy jest wyłączone, Fibly nigdy nie dołącza tego nagłówka.",[70,164,165],{},"Zapisz. Pole hasła\u002Ftokena jest tylko do zapisu: po zapisaniu nie jest już nigdy pokazywane w\npanelu.",[16,167,168,169,172,173,175],{},"Pierwsze utworzone połączenie automatycznie generuje też ",[20,170,171],{},"klucz podpisujący"," Twojego\nobszaru roboczego (zobacz ",[34,174,161],{"href":160},"\nponiżej).",[49,177,179],{"id":178},"budowanie-narzędzia","Budowanie narzędzia",[16,181,182,183,186],{},"W ramach połączenia dodaj jedno lub więcej ",[20,184,185],{},"narzędzi"," — każde odpowiada jednemu wywołaniu HTTP:",[67,188,189,195,304,311],{},[70,190,85,191,194],{},[20,192,193],{},"Dodaj narzędzie"," na stronie połączenia.",[70,196,91,197],{},[93,198,199,209,232,246,252,285,295],{},[70,200,201,204,205,208],{},[20,202,203],{},"Nazwa narzędzia"," — identyfikator, którego agent używa wewnętrznie do wywołania tego\nnarzędzia, np. ",[108,206,207],{},"get_order_status",". Tylko litery, cyfry i podkreślenia, unikalny we wszystkich\nTwoich połączeniach.",[70,210,211,214,215,218,219,218,222,218,225,228,229,82],{},[20,212,213],{},"Metoda HTTP"," — ",[108,216,217],{},"GET",", ",[108,220,221],{},"POST",[108,223,224],{},"PUT",[108,226,227],{},"PATCH"," lub ",[108,230,231],{},"DELETE",[70,233,234,237,238,241,242,245],{},[20,235,236],{},"Ścieżka"," — względem adresu bazowego połączenia, np. ",[108,239,240],{},"\u002Forders\u002F{order_ref}",". Ujmij fragment\nw ",[108,243,244],{},"{ }",", aby odwołać się do parametru (zobacz niżej) — zostanie podstawiony wartością\nargumentu i zakodowany do URL przed wywołaniem.",[70,247,248,251],{},[20,249,250],{},"Opis"," — podpowiedź, którą model AI czyta, aby zdecydować, kiedy i jak wywołać to\nnarzędzie. Opisz, co robi i kiedy jest przydatne; model nigdy nie pokazuje tego tekstu\nklientowi.",[70,253,254,257,258,218,261,264,265,218,268,218,271,218,274,228,277,280,281,284],{},[20,255,256],{},"Parametry"," — argumenty, które model może uzupełnić. Dla każdego dodaj ",[20,259,260],{},"nazwę",[20,262,263],{},"typ","\n(",[108,266,267],{},"String",[108,269,270],{},"Number",[108,272,273],{},"Integer",[108,275,276],{},"Boolean",[108,278,279],{},"Enum"," z ustaloną listą wartości), czy jest\n",[20,282,283],{},"wymagany",", oraz opis.",[70,286,287,290,291,82],{},[20,288,289],{},"Wymaga potwierdzenia"," — zobacz ",[34,292,294],{"href":293},"#potwierdzenie-requires_confirmation","niżej",[70,296,297,300,301,82],{},[20,298,299],{},"Wymaga weryfikacji tożsamości"," — zobacz\n",[34,302,294],{"href":303},"#weryfikacja-tozsamosci-requires_verification",[70,305,306,307,310],{},"Edytor narzędzia ma przełącznik ",[20,308,309],{},"Angielski\u002FPolski",": opis narzędzia i opis każdego parametru są\nlokalizowane, dzięki czemu model rozumuje w języku, w jakim toczy się rozmowa. Angielski opis\njest wymagany; pozostałe języki, jeśli puste, spadają do niego.",[70,312,313,314,317],{},"Zapisz i włącz przełącznik ",[20,315,316],{},"Włączone",", gdy narzędzie ma być dostępne dla bota na żywo.",[49,319,321],{"id":320},"jak-agent-wywołuje-twój-webhook","Jak agent wywołuje Twój webhook",[16,323,324],{},"Gdy model zdecyduje się użyć narzędzia, Fibly buduje i wysyła za Ciebie żądanie HTTP:",[93,326,327,338,361,364,373],{},[70,328,329,330,333,334,337],{},"Każdy znacznik ",[108,331,332],{},"{nazwa}"," w ",[20,335,336],{},"ścieżce"," jest podstawiany wartością odpowiadającego argumentu\n(zakodowaną do URL).",[70,339,340,341,344,345,347,348,350,351,354,355,347,357,347,359,82],{},"Pozostałe argumenty trafiają do ",[20,342,343],{},"query string"," dla ",[108,346,217],{},"\u002F",[108,349,231],{},", albo do ",[20,352,353],{},"treści JSON"," dla\n",[108,356,221],{},[108,358,224],{},[108,360,227],{},[70,362,363],{},"Uwierzytelnianie Twojego połączenia (Basic\u002FBearer) jest stosowane automatycznie.",[70,365,366,367,369,370,372],{},"Jeśli ustawienie połączenia ",[20,368,152],{}," jest włączone, dołączany jest\npodpisany nagłówek ",[108,371,156],{}," — zobacz kolejną sekcję. Domyślnie jest wyłączone,\nwięc dopóki go nie włączysz, Twój webhook w ogóle nie otrzyma tego nagłówka.",[70,374,375,376,379,380,383],{},"Wywołanie ma stały limit czasu ",[20,377,378],{},"ok. 10 sekund",", a Fibly ",[20,381,382],{},"nie"," podąża za przekierowaniami —\njeśli Twoje API przekierowuje (30x), zaktualizuj adres bazowy połączenia zamiast polegać na\nprzekierowaniu.",[385,386,388],"h3",{"id":387},"co-widzi-agent-w-odpowiedzi","Co widzi agent w odpowiedzi",[93,390,391,398],{},[70,392,393,394,397],{},"Odpowiedź ",[20,395,396],{},"2xx"," z treścią JSON trafia do modelu jako dane strukturalne, których może użyć w\nodpowiedzi. 2xx z treścią inną niż JSON jest przekazywane jako zwykły tekst.",[70,399,393,400,403],{},[20,401,402],{},"inna niż 2xx",", przekroczenie limitu czasu lub błąd połączenia są traktowane jako\nniepowodzenie narzędzia — model dowiaduje się, że wywołanie się nie powiodło, i odpowiednio\ndostosowuje odpowiedź (w tym przypadku nie widzi Twojego surowego kodu statusu ani treści).",[16,405,406],{},"Projektuj odpowiedzi sukcesu swojego webhooka tak, by były małe i bezpośrednio użyteczne — to, co\nzwrócisz w treści JSON 2xx, jest tym, czego model używa do odpowiedzi klientowi.",[49,408,410,411,413],{"id":409},"weryfikacja-wywołującego-x-fibly-verification","Weryfikacja wywołującego (",[108,412,156],{},")",[16,415,416,417,419,420,423,424,426],{},"Włącz ",[20,418,152],{}," na połączeniu (domyślnie wyłączone — zobacz\n",[34,421,59],{"href":422},"#budowanie-polaczenia"," wyżej), a każde wywołanie na tym połączeniu będzie\nnieść podpisany token JWT w nagłówku ",[108,425,156],{},". To część, którą musi zaimplementować\nTwój deweloper, i ma znaczenie nawet jeśli Twoje API wymaga też własnych danych uwierzytelniających\nBasic\u002FBearer: te dane dowodzą jedynie, że żądanie przyszło skądś z backendu Fibly; podpisany token\ndowodzi, że przyszło z konkretnego, skonfigurowanego połączenia Twojego obszaru roboczego, i niesie\nkontekst rozmowy oraz klienta potrzebny do podjęcia decyzji autoryzacyjnych. Gdy włączysz ten\nprzełącznik, Fibly zacznie dołączać nagłówek do każdego wywołania na tym połączeniu —\nweryfikacja go po Twojej stronie to osobny krok, opisany niżej; dopóki go nie zaimplementujesz,\nnagłówek po prostu dociera nieużywany.",[16,428,429,432],{},[20,430,431],{},"Po co to istnieje."," Fibly nie zna Twojego modelu danych, więc nie może sprawdzić na przykład,\nczy zamówienie, o które pyta klient, rzeczywiście do niego należy. To, co może zrobić, to\nprzekazać Ci kryptograficznie podpisane, odporne na manipulację oświadczenie o tym, kim jest\nodwiedzający (na tyle, na ile sięga własna weryfikacja Fibly) i do jakiej rozmowy należy\nwywołanie — tak, aby Twój serwer mógł sam wykonać tę weryfikację własności.",[385,434,436],{"id":435},"endpoint-jwks","Endpoint JWKS",[16,438,439,440,443,444,82],{},"Fibly generuje dla Twojego obszaru roboczego parę kluczy RSA-2048 przy pierwszym utworzeniu połączenia.\nKlucz prywatny nigdy nie opuszcza Fibly; klucz publiczny jest publikowany pod endpointem ",[20,441,442],{},"JWKS","\nTwojego obszaru roboczego — publicznym, niewymagającym uwierzytelnienia adresem URL, który zwraca Twoje\naktywne (i niedawno zrotowane) klucze publiczne w standardowym formacie JWKS ",[108,445,446],{},"{\"keys\": [...]}",[16,448,449,452,453,456,457,460,461,464,465,468,469,472,473,476,477,480,481,488],{},[20,450,451],{},"Skopiuj swój adres URL JWKS z panelu — nie próbuj go samodzielnie budować."," Jest on stały dla\nTwojego obszaru roboczego i widoczny obok ",[20,454,455],{},"ID klucza"," oraz ",[20,458,459],{},"ID połączenia"," w panelu ",[20,462,463],{},"Klucze\npodpisujące",", tuż przy przycisku ",[20,466,467],{},"Pobierz klucz publiczny (PEM)"," oraz akcji ",[20,470,471],{},"Rotuj klucz",".\nSkopiuj adres URL JWKS do stałej ",[108,474,475],{},"JWKS_URL",", a ID połączenia do stałej ",[108,478,479],{},"CONNECTION_ID"," w\nprzykładach kodu poniżej — obie wartości powinny być zaszytą na stałe konfiguracją po stronie\nTwojego serwera, a nie czymś wyliczanym z żądania. Rotacja od razu zaczyna podpisywać nowe tokeny\nnowym kluczem, ale poprzedni klucz pozostaje publikowany w JWKS przez krótkie okno zakładki, tak\naby tokeny już będące w drodze nadal się weryfikowały — ",[20,482,483,484,487],{},"pobieraj klucze po ",[108,485,486],{},"kid"," i nie zaszywaj\nna stałe treści jednego klucza",", w przeciwnym razie rotacja zepsuje Twoją weryfikację.",[385,490,492],{"id":491},"tabela-roszczeń-claims","Tabela roszczeń (claims)",[16,494,495,496,499,500,502],{},"Token to zwarty JWS, algorytm ",[20,497,498],{},"RS256",", z identyfikatorem klucza podpisującego w nagłówku JWT\njako ",[108,501,486],{},". Jego treść (payload):",[504,505,506,525],"table",{},[507,508,509],"thead",{},[510,511,512,516,519,522],"tr",{},[513,514,515],"th",{},"Roszczenie",[513,517,518],{},"Typ",[513,520,521],{},"Zawsze obecne?",[513,523,524],{},"Znaczenie",[526,527,528,548,567,585,600,617,638,653,681,701,715,729,760,782,804,819,836,855],"tbody",{},[510,529,530,536,539,542],{},[531,532,533],"td",{},[108,534,535],{},"iss",[531,537,538],{},"string",[531,540,541],{},"zawsze",[531,543,544,545,82],{},"Zawsze literalny ciąg ",[108,546,547],{},"\"fibly\"",[510,549,550,555,558,560],{},[531,551,552],{},[108,553,554],{},"aud",[531,556,557],{},"string (UUID)",[531,559,541],{},[531,561,562,563,566],{},"Id ",[20,564,565],{},"połączenia",", do którego należy wywołanie.",[510,568,569,574,576,578],{},[531,570,571],{},[108,572,573],{},"tenant_id",[531,575,557],{},[531,577,541],{},[531,579,580,581,584],{},"Id Twojego obszaru roboczego. Przydatne jako opcjonalna dodatkowa weryfikacja, że token został podpisany dla Twojego obszaru roboczego — nie używaj go do budowania adresu URL JWKS; ten adres jest stały, skopiuj go z panelu (zobacz ",[34,582,436],{"href":583},"#endpoint-jwks"," wyżej).",[510,586,587,592,595,597],{},[531,588,589],{},[108,590,591],{},"iat",[531,593,594],{},"liczba (znacznik Unix)",[531,596,541],{},[531,598,599],{},"Kiedy token został wystawiony.",[510,601,602,607,609,611],{},[531,603,604],{},[108,605,606],{},"nbf",[531,608,594],{},[531,610,541],{},[531,612,613,614,616],{},"To samo co ",[108,615,591],{}," — token nie jest ważny wcześniej.",[510,618,619,624,626,628],{},[531,620,621],{},[108,622,623],{},"exp",[531,625,594],{},[531,627,541],{},[531,629,630,631,634,635,637],{},"Wygaśnięcie, ok. ",[20,632,633],{},"120 sekund"," po ",[108,636,591],{},". Token ma uwierzytelniać to jedno wywołanie, nie być użyty ponownie później.",[510,639,640,645,648,650],{},[531,641,642],{},[108,643,644],{},"jti",[531,646,647],{},"string (hex)",[531,649,541],{},[531,651,652],{},"Unikalny identyfikator tokena, przydatny, jeśli chcesz odrzucać dokładne powtórzenia.",[510,654,655,660,666,671],{},[531,656,657],{},[108,658,659],{},"conversation_id",[531,661,662,663],{},"string (UUID) lub ",[108,664,665],{},"null",[531,667,668,669,413],{},"zawsze (wartość może być ",[108,670,665],{},[531,672,673,674,676,677,680],{},"Wątek rozmowy, w którym nastąpiło wywołanie. ",[108,675,665],{}," dla wywołań spoza prawdziwej rozmowy, np. akcji ",[20,678,679],{},"Test"," w panelu.",[510,682,683,688,690,692],{},[531,684,685],{},[108,686,687],{},"language",[531,689,538],{},[531,691,541],{},[531,693,694,695,228,698,82],{},"Aktywny język bota dla tego wywołania, np. ",[108,696,697],{},"en",[108,699,700],{},"pl",[510,702,703,708,710,712],{},[531,704,705],{},[108,706,707],{},"tool_name",[531,709,538],{},[531,711,541],{},[531,713,714],{},"Nazwa wywołanego narzędzia.",[510,716,717,722,724,726],{},[531,718,719],{},[108,720,721],{},"tool_call_id",[531,723,647],{},[531,725,541],{},[531,727,728],{},"Unikalny identyfikator tego konkretnego wywołania, przydatny do korelacji z własnymi logami.",[510,730,731,736,738,741],{},[531,732,733],{},[108,734,735],{},"channel",[531,737,538],{},[531,739,740],{},"tylko wewnątrz prawdziwej rozmowy",[531,742,743,744,747,748,218,751,218,754,228,757,82],{},"Kanał, na którym toczy się rozmowa: ",[108,745,746],{},"chat"," (widget na stronie), ",[108,749,750],{},"email",[108,752,753],{},"whatsapp",[108,755,756],{},"facebook",[108,758,759],{},"instagram",[510,761,762,767,770,772],{},[531,763,764],{},[108,765,766],{},"email_verified",[531,768,769],{},"boolean",[531,771,740],{},[531,773,774,775,778,779,781],{},"Czy e-mail odwiedzającego jest ogólnie zaufany: ukończył własną weryfikację Fibly (link magiczny, w tym powracającego odwiedzającego rozpoznanego dzięki zapisanej w przeglądarce weryfikacji ważnej do 90 dni), ",[20,776,777],{},"lub"," rozmowa przyszła kanałem e-mail (nadawca e-maila to z natury silniejszy sygnał tożsamości). To jedyna flaga, którą sprawdza sama bramka ",[20,780,299],{}," — zobacz niżej.",[510,783,784,789,792,794],{},[531,785,786],{},[108,787,788],{},"channel_data",[531,790,791],{},"object",[531,793,740],{},[531,795,796,797,290,799,803],{},"Kontekst właściwy dla danego kanału, zagnieżdżony pod kluczem odpowiadającym ",[108,798,735],{},[34,800,802],{"href":801},"#dane-kanalu-channel_data","Dane kanału"," niżej.",[510,805,806,811,813,816],{},[531,807,808],{},[108,809,810],{},"customer_id",[531,812,557],{},[531,814,815],{},"tylko gdy rozmowa ma zidentyfikowanego klienta",[531,817,818],{},"Wewnętrzny identyfikator tego klienta w Fibly.",[510,820,821,826,831,833],{},[531,822,823],{},[108,824,825],{},"name",[531,827,828,829],{},"string lub ",[108,830,665],{},[531,832,815],{},[531,834,835],{},"Imię\u002Fnazwa klienta, jeśli znane.",[510,837,838,842,846,848],{},[531,839,840],{},[108,841,750],{},[531,843,828,844],{},[108,845,665],{},[531,847,815],{},[531,849,850,851,854],{},"E-mail klienta zapisany w systemie. ",[20,852,853],{},"To nie to samo co zweryfikowany"," — zobacz ostrzeżenie niżej.",[510,856,857,862,866,868],{},[531,858,859],{},[108,860,861],{},"phone",[531,863,828,864],{},[108,865,665],{},[531,867,815],{},[531,869,870],{},"Numer telefonu klienta, jeśli znany.",[16,872,873],{},"Transkrypt rozmowy nigdy nie jest w nim zawarty — tylko metadane rozmowy\u002Fklienta.",[385,875,877,878,413],{"id":876},"dane-kanału-channel_data","Dane kanału (",[108,879,788],{},[16,881,882,884,885,890,891,894],{},[108,883,788],{}," niesie kontekst właściwy dla kanału, na którym toczyła się rozmowa. ",[20,886,887,888],{},"Obecny jest\ntylko jeden klucz — ten odpowiadający roszczeniu ",[108,889,735],{}," — odczytaj go jako\n",[108,892,893],{},"claims[\"channel_data\"][claims[\"channel\"]]",", zamiast sprawdzać kształt dla każdego kanału z osobna:",[504,896,897,913],{},[507,898,899],{},[510,900,901,905,910],{},[513,902,903],{},[108,904,735],{},[513,906,907,908],{},"klucz w ",[108,909,788],{},[513,911,912],{},"pola",[526,914,915,956,970,984,1000],{},[510,916,917,922,926],{},[531,918,919,921],{},[108,920,746],{}," (widget na stronie)",[531,923,924],{},[108,925,746],{},[531,927,928,218,931,218,934,218,937,218,940,218,943,946,947,347,950,347,953],{},[108,929,930],{},"ip",[108,932,933],{},"user_agent",[108,935,936],{},"browser_name",[108,938,939],{},"browser_version",[108,941,942],{},"os_name",[108,944,945],{},"os_version"," oraz geolokalizacja ",[108,948,949],{},"country_code",[108,951,952],{},"country",[108,954,955],{},"city",[510,957,958,962,966],{},[531,959,960],{},[108,961,750],{},[531,963,964],{},[108,965,750],{},[531,967,968],{},[108,969,750],{},[510,971,972,976,980],{},[531,973,974],{},[108,975,753],{},[531,977,978],{},[108,979,753],{},[531,981,982],{},[108,983,861],{},[510,985,986,990,994],{},[531,987,988],{},[108,989,756],{},[531,991,992],{},[108,993,756],{},[531,995,996,999],{},[108,997,998],{},"psid"," (identyfikator użytkownika przypisany do strony Messengera)",[510,1001,1002,1006,1010],{},[531,1003,1004],{},[108,1005,759],{},[531,1007,1008],{},[108,1009,759],{},[531,1011,1012,1015],{},[108,1013,1014],{},"igsid"," (identyfikator użytkownika przypisany do konta Instagram)",[16,1017,1018,1019,1021,1022,1024],{},"Tylko kanał ",[108,1020,746],{}," niesie adres IP, user agent, przeglądarkę\u002Fsystem operacyjny oraz geolokalizację\n— te dane pochodzą z sesji przeglądarki odwiedzającego na Twojej stronie, której nie ma dla\npozostałych kanałów. Każde pole, którego Fibly nie ma dla danego wywołania, ma wartość ",[108,1023,665],{},"\nzamiast być pominięte, więc kształt dla danego kanału jest zawsze taki sam.",[1026,1027,1028],"blockquote",{},[16,1029,1030,1035],{},[20,1031,1032,1034],{},[108,1033,788],{}," to dane osobowe."," Adres IP, odcisk przeglądarki\u002Fsystemu operacyjnego, e-mail,\nnumer telefonu oraz identyfikatory Messenger\u002FInstagram to w większości reżimów ochrony danych\ndane osobowe. Przetwarzaj, przechowuj i loguj je odpowiednio — i nie przekazuj ich dalej tam,\ngdzie nie przekazałbyś reszty danych kontaktowych klienta.",[1026,1037,1038],{},[16,1039,1040,1046,1047,1049,1050,1052,1053,1056,1057,1059,1060,1062,1063,1065],{},[20,1041,1042,1043,1045],{},"Roszczenie ",[108,1044,750],{}," nie jest automatycznie zweryfikowane."," Odzwierciedla e-mail, jaki Fibly ma\nzapisany dla klienta, niezależnie od tego, czy został udowodniony. Zanim zaufasz roszczeniu\n",[108,1048,750],{}," w czymkolwiek istotnym, sprawdź, czy ",[108,1051,766],{}," ma wartość ",[108,1054,1055],{},"true",". Jeśli Twoje\nnarzędzie ma włączone ",[20,1058,299],{}," w panelu, Fibly gwarantuje, że\n",[108,1061,766],{}," jest ",[108,1064,1055],{},", zanim Twój webhook zostanie w ogóle wywołany dla tego narzędzia —\nzobacz kolejną sekcję.",[385,1067,1069],{"id":1068},"weryfikacja-tokena-krok-po-kroku","Weryfikacja tokena, krok po kroku",[67,1071,1072,1078,1088,1091,1114,1117],{},[70,1073,1074,1075,1077],{},"Odczytaj nagłówek ",[108,1076,156],{}," z przychodzącego żądania. Jeśli go brakuje, potraktuj\nwywołanie jako niezweryfikowane — zdecyduj o własnej polityce (odrzuć je albo udostępnij tylko\ndane nieistotne z punktu widzenia prywatności).",[70,1079,1080,1081,1084,1085,1087],{},"Pobierz (i cache'uj) swój ",[20,1082,1083],{},"stały"," adres JWKS — ten skopiowany z panelu Klucze podpisujące, a\nnie wyliczony samodzielnie — i z nagłówka tokena wybierz klucz, którego ",[108,1086,486],{}," pasuje.",[70,1089,1090],{},"Zweryfikuj podpis RS256 tokena względem tego klucza.",[70,1092,1093,1094,1096,1097,1099,1100,1102,1103,1099,1105,1107,1108,1110,1111,1113],{},"Zwaliduj ",[108,1095,623],{}," (nie wygasł), ",[108,1098,535],{}," (równa się ",[108,1101,547],{},") oraz ",[108,1104,554],{},[20,1106,459],{},"\ntego połączenia, również skopiowanemu z panelu Klucze podpisujące). Sprawdzaj ",[108,1109,554],{}," zawsze, nie\ntylko wtedy, gdy chcesz „przypiąć” weryfikację — to on powstrzymuje token podpisany dla innego\npołączenia przed zweryfikowaniem się tutaj. Opcjonalnie sprawdź też, czy roszczenie ",[108,1112,573],{},"\nrówna się Twojemu id obszaru roboczego, jako dodatkowe zabezpieczenie.",[70,1115,1116],{},"Dopiero gdy podpis i standardowe roszczenia się zgadzają, zaufaj reszcie treści.",[70,1118,1119,1120,1123],{},"Wykonaj ",[20,1121,1122],{},"własną"," weryfikację własności zasobu na podstawie zweryfikowanych roszczeń — Fibly\nnie zna Twojego modelu danych i nie może zrobić tego za Ciebie.",[16,1125,1126,1127,1129],{},"Ponieważ zrotowany klucz pozostaje ważny przez krótkie okno zakładki, klient JWKS powinien\ncache'ować odpowiedzi na krótko i pobierać je ponownie przy nierozpoznanym ",[108,1128,486],{},", zamiast\ncache'ować jeden klucz na stałe.",[16,1131,1132,1135,1136,1138,1139,1143],{},[20,1133,1134],{},"Uwaga dotycząca bezpieczeństwa: nigdy nie pozwól tokenowi wskazać, którym kluczem go\nzweryfikować."," Odczytanie ",[108,1137,573],{}," (lub dowolnego innego roszczenia) z ",[1140,1141,1142],"em",{},"niezweryfikowanego","\ntokena i użycie go do zbudowania adresu URL JWKS, który następnie pobierasz, jest niebezpieczne —\ntoken podpisany kluczem innego tenanta Fibly zostałby pobrany i zweryfikowany względem JWKS tego\ntenanta, pozwalając komukolwiek, kto potrafi zdobyć podpisany token z własnego (kontrolowanego\nprzez atakującego) obszaru roboczego, podszyć się pod wywołania Twojego webhooka. Zawsze\nweryfikuj względem jednego, stałego adresu URL JWKS skopiowanego z panelu Klucze podpisujące\nTwojego połączenia — nigdy adresu zbudowanego na podstawie samego tokena.",[385,1145,1147],{"id":1146},"przykład-narzędzie-statusu-zamówienia","Przykład: narzędzie statusu zamówienia",[16,1149,1150,1151,1153,1154,1157,1158,1161,1162,1165,1166,1168,1169,1171],{},"Załóżmy, że budujesz narzędzie ",[108,1152,207],{},": ",[108,1155,1156],{},"GET \u002Forders\u002F{order_ref}"," na połączeniu Twojego\nAPI zamówień, z jednym wymaganym parametrem ",[108,1159,1160],{},"order_ref"," typu string i włączonym ",[20,1163,1164],{},"Wymaga\nweryfikacji tożsamości",". Połączenie ma też włączone ",[20,1167,152],{}," — bez tego\nnagłówek ",[108,1170,156],{}," w ogóle by nie dotarł, a kroki 3-4 poniżej nie byłyby możliwe.",[67,1173,1174,1189,1202,1217],{},[70,1175,1176,1177,1180,1181,1184,1185,1188],{},"Klient pyta „gdzie jest moje zamówienie 12345?\". Model ma ",[108,1178,1179],{},"order_ref=\"12345\"",", ale\nodwiedzający nie zweryfikował jeszcze e-maila w tej rozmowie. Ponieważ narzędzie wymaga\nweryfikacji, ",[20,1182,1183],{},"Fibly w ogóle nie wywołuje Twojego webhooka"," — zwraca modelowi status\n",[108,1186,1187],{},"verification_required",", a ten prosi klienta o weryfikację e-maila (własny mechanizm linku\nmagicznego Fibly) i ponawia próbę po jej ukończeniu.",[70,1190,1191,1192],{},"Po weryfikacji Fibly wywołuje:\n",[1193,1194,1199],"pre",{"className":1195,"code":1197,"language":1198},[1196],"language-text","GET https:\u002F\u002Fapi.example.com\u002Forders\u002F12345\nAuthorization: Bearer \u003Ctoken Twojego połączenia>\nX-Fibly-Verification: \u003Cjwt>\n","text",[108,1200,1197],{"__ignoreMap":1201},"",[70,1203,1204,1205,1207,1208,1210,1211,1213,1214,82],{},"Twój serwer weryfikuje JWT tak jak opisano wyżej. Ponieważ to narzędzie wymaga weryfikacji,\n",[108,1206,766],{}," jest gwarantowane jako ",[108,1209,1055],{},", a ",[108,1212,750],{}," to zweryfikowany adres odwiedzającego,\nnp. ",[108,1215,1216],{},"jane@example.com",[70,1218,1219,1220,1223,1224,1226,1227,1266,1267,1270],{},"Twój serwer wyszukuje zamówienie ",[108,1221,1222],{},"12345"," we własnej bazie danych i porównuje e-mail jego\nwłaściciela ze zweryfikowanym ",[108,1225,750],{}," z tokena. Jeśli się zgadzają, zwróć status:\n",[1193,1228,1232],{"className":1229,"code":1230,"language":1231,"meta":1201,"style":1201},"language-json shiki shiki-themes github-dark","{ \"order_ref\": \"12345\", \"status\": \"shipped\" }\n","json",[108,1233,1234],{"__ignoreMap":1201},[1235,1236,1239,1243,1247,1249,1253,1255,1258,1260,1263],"span",{"class":1237,"line":1238},"line",1,[1235,1240,1242],{"class":1241},"s95oV","{ ",[1235,1244,1246],{"class":1245},"sDLfK","\"order_ref\"",[1235,1248,1153],{"class":1241},[1235,1250,1252],{"class":1251},"sU2Wk","\"12345\"",[1235,1254,218],{"class":1241},[1235,1256,1257],{"class":1245},"\"status\"",[1235,1259,1153],{"class":1241},[1235,1261,1262],{"class":1251},"\"shipped\"",[1235,1264,1265],{"class":1241}," }\n","\nJeśli się nie zgadzają — albo zamówienie nie istnieje — zwróć ",[20,1268,1269],{},"404",", a nie 403: 403\npotwierdziłby atakującemu, że zamówienie 12345 w ogóle istnieje.",[49,1272,1274],{"id":1273},"przykłady-kodu-weryfikacja-tokena","Przykłady kodu: weryfikacja tokena",[16,1276,1277,1278,1280,1281,347,1283,347,1285,1287,1288,1290,1291,1293],{},"Każdy z poniższych przykładów odczytuje nagłówek, pobiera JWKS (z cache'owaniem), weryfikuje\npodpis RS256 po ",[108,1279,486],{},", sprawdza ",[108,1282,623],{},[108,1284,535],{},[108,1286,554],{}," i wykonuje tę samą weryfikację własności e-maila\nco w przykładzie wyżej. Podmień ",[108,1289,475],{}," i ",[108,1292,479],{}," na wartości widoczne w panelu Klucze\npodpisujące tego połączenia — obie to zaszyta na stałe konfiguracja, nigdy niewyliczana z tokena\n(zobacz uwagę o bezpieczeństwie wyżej).",[1295,1296,1298,1888,2446],"code-tabs",{":captions":1297},"{\"python\":\"PyJWT\",\"node\":\"jose\",\"php\":\"firebase\u002Fphp-jwt\"}",[1299,1300,1301],"template",{"v-slot:python":1201},[1193,1302,1306],{"className":1303,"code":1304,"language":1305,"meta":1201,"style":1201},"language-python shiki shiki-themes github-dark","import jwt\nfrom jwt import PyJWKClient\n\n# Skopiuj obie wartości z panelu Klucze podpisujące tego połączenia i zaszyj je na\n# stałe jako konfigurację — nigdy nie wyznaczaj JWKS_URL na podstawie roszczenia z\n# (niezweryfikowanego) tokena, bo token podpisany kluczem innego tenanta mógłby się\n# tu zweryfikować.\nJWKS_URL = \"https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json\"  # skopiuj z panelu\nCONNECTION_ID = \"c1a2e3f4-5678-4abc-9def-0123456789ab\"  # „ID połączenia” w panelu Klucze podpisujące\n\n# PyJWKClient cache'uje odpowiedź JWKS i pobiera ją ponownie przy nieznanym `kid`.\n_jwks_client = PyJWKClient(JWKS_URL, cache_keys=True)\n\ndef verify_fibly_token(token: str) -> dict:\n    signing_key = _jwks_client.get_signing_key_from_jwt(token)\n    claims = jwt.decode(\n        token,\n        signing_key.key,\n        algorithms=[\"RS256\"],\n        audience=CONNECTION_ID,\n        issuer=\"fibly\",\n        options={\"require\": [\"exp\", \"iat\", \"iss\", \"aud\"]},\n    )\n    return claims\n\n\ndef handle_get_order_status(order_ref: str, headers: dict) -> tuple[dict, int]:\n    token = headers.get(\"X-Fibly-Verification\", \"\")\n    if not token:\n        return {\"error\": \"missing verification token\"}, 401\n    try:\n        claims = verify_fibly_token(token)\n    except Exception:\n        return {\"error\": \"invalid verification token\"}, 401\n\n    order = get_order(order_ref)  # Twoje własne wyszukiwanie\n    if order is None:\n        return {\"error\": \"not found\"}, 404\n\n    verified_email = (claims.get(\"email\") or \"\").lower()\n    if not claims.get(\"email_verified\") or order.customer_email.lower() != verified_email:\n        return {\"error\": \"not found\"}, 404  # 404, nie 403 — nie potwierdzaj istnienia zamówienia\n\n    return {\"order_ref\": order_ref, \"status\": order.status}, 200\n","python",[108,1307,1308,1317,1331,1338,1345,1351,1357,1363,1377,1390,1395,1401,1429,1434,1459,1470,1481,1487,1493,1510,1522,1534,1572,1578,1587,1592,1597,1628,1649,1661,1684,1692,1703,1714,1732,1737,1751,1767,1786,1791,1817,1843,1863,1868],{"__ignoreMap":1201},[1235,1309,1310,1314],{"class":1237,"line":1238},[1235,1311,1313],{"class":1312},"snl16","import",[1235,1315,1316],{"class":1241}," jwt\n",[1235,1318,1320,1323,1326,1328],{"class":1237,"line":1319},2,[1235,1321,1322],{"class":1312},"from",[1235,1324,1325],{"class":1241}," jwt ",[1235,1327,1313],{"class":1312},[1235,1329,1330],{"class":1241}," PyJWKClient\n",[1235,1332,1334],{"class":1237,"line":1333},3,[1235,1335,1337],{"emptyLinePlaceholder":1336},true,"\n",[1235,1339,1341],{"class":1237,"line":1340},4,[1235,1342,1344],{"class":1343},"sAwPA","# Skopiuj obie wartości z panelu Klucze podpisujące tego połączenia i zaszyj je na\n",[1235,1346,1348],{"class":1237,"line":1347},5,[1235,1349,1350],{"class":1343},"# stałe jako konfigurację — nigdy nie wyznaczaj JWKS_URL na podstawie roszczenia z\n",[1235,1352,1354],{"class":1237,"line":1353},6,[1235,1355,1356],{"class":1343},"# (niezweryfikowanego) tokena, bo token podpisany kluczem innego tenanta mógłby się\n",[1235,1358,1360],{"class":1237,"line":1359},7,[1235,1361,1362],{"class":1343},"# tu zweryfikować.\n",[1235,1364,1366,1368,1371,1374],{"class":1237,"line":1365},8,[1235,1367,475],{"class":1245},[1235,1369,1370],{"class":1312}," =",[1235,1372,1373],{"class":1251}," \"https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json\"",[1235,1375,1376],{"class":1343},"  # skopiuj z panelu\n",[1235,1378,1380,1382,1384,1387],{"class":1237,"line":1379},9,[1235,1381,479],{"class":1245},[1235,1383,1370],{"class":1312},[1235,1385,1386],{"class":1251}," \"c1a2e3f4-5678-4abc-9def-0123456789ab\"",[1235,1388,1389],{"class":1343},"  # „ID połączenia” w panelu Klucze podpisujące\n",[1235,1391,1393],{"class":1237,"line":1392},10,[1235,1394,1337],{"emptyLinePlaceholder":1336},[1235,1396,1398],{"class":1237,"line":1397},11,[1235,1399,1400],{"class":1343},"# PyJWKClient cache'uje odpowiedź JWKS i pobiera ją ponownie przy nieznanym `kid`.\n",[1235,1402,1404,1407,1410,1413,1415,1417,1421,1423,1426],{"class":1237,"line":1403},12,[1235,1405,1406],{"class":1241},"_jwks_client ",[1235,1408,1409],{"class":1312},"=",[1235,1411,1412],{"class":1241}," PyJWKClient(",[1235,1414,475],{"class":1245},[1235,1416,218],{"class":1241},[1235,1418,1420],{"class":1419},"s9osk","cache_keys",[1235,1422,1409],{"class":1312},[1235,1424,1425],{"class":1245},"True",[1235,1427,1428],{"class":1241},")\n",[1235,1430,1432],{"class":1237,"line":1431},13,[1235,1433,1337],{"emptyLinePlaceholder":1336},[1235,1435,1437,1440,1444,1447,1450,1453,1456],{"class":1237,"line":1436},14,[1235,1438,1439],{"class":1312},"def",[1235,1441,1443],{"class":1442},"svObZ"," verify_fibly_token",[1235,1445,1446],{"class":1241},"(token: ",[1235,1448,1449],{"class":1245},"str",[1235,1451,1452],{"class":1241},") -> ",[1235,1454,1455],{"class":1245},"dict",[1235,1457,1458],{"class":1241},":\n",[1235,1460,1462,1465,1467],{"class":1237,"line":1461},15,[1235,1463,1464],{"class":1241},"    signing_key ",[1235,1466,1409],{"class":1312},[1235,1468,1469],{"class":1241}," _jwks_client.get_signing_key_from_jwt(token)\n",[1235,1471,1473,1476,1478],{"class":1237,"line":1472},16,[1235,1474,1475],{"class":1241},"    claims ",[1235,1477,1409],{"class":1312},[1235,1479,1480],{"class":1241}," jwt.decode(\n",[1235,1482,1484],{"class":1237,"line":1483},17,[1235,1485,1486],{"class":1241},"        token,\n",[1235,1488,1490],{"class":1237,"line":1489},18,[1235,1491,1492],{"class":1241},"        signing_key.key,\n",[1235,1494,1496,1499,1501,1504,1507],{"class":1237,"line":1495},19,[1235,1497,1498],{"class":1419},"        algorithms",[1235,1500,1409],{"class":1312},[1235,1502,1503],{"class":1241},"[",[1235,1505,1506],{"class":1251},"\"RS256\"",[1235,1508,1509],{"class":1241},"],\n",[1235,1511,1513,1516,1518,1520],{"class":1237,"line":1512},20,[1235,1514,1515],{"class":1419},"        audience",[1235,1517,1409],{"class":1312},[1235,1519,479],{"class":1245},[1235,1521,38],{"class":1241},[1235,1523,1525,1528,1530,1532],{"class":1237,"line":1524},21,[1235,1526,1527],{"class":1419},"        issuer",[1235,1529,1409],{"class":1312},[1235,1531,547],{"class":1251},[1235,1533,38],{"class":1241},[1235,1535,1537,1540,1542,1545,1548,1551,1554,1556,1559,1561,1564,1566,1569],{"class":1237,"line":1536},22,[1235,1538,1539],{"class":1419},"        options",[1235,1541,1409],{"class":1312},[1235,1543,1544],{"class":1241},"{",[1235,1546,1547],{"class":1251},"\"require\"",[1235,1549,1550],{"class":1241},": [",[1235,1552,1553],{"class":1251},"\"exp\"",[1235,1555,218],{"class":1241},[1235,1557,1558],{"class":1251},"\"iat\"",[1235,1560,218],{"class":1241},[1235,1562,1563],{"class":1251},"\"iss\"",[1235,1565,218],{"class":1241},[1235,1567,1568],{"class":1251},"\"aud\"",[1235,1570,1571],{"class":1241},"]},\n",[1235,1573,1575],{"class":1237,"line":1574},23,[1235,1576,1577],{"class":1241},"    )\n",[1235,1579,1581,1584],{"class":1237,"line":1580},24,[1235,1582,1583],{"class":1312},"    return",[1235,1585,1586],{"class":1241}," claims\n",[1235,1588,1590],{"class":1237,"line":1589},25,[1235,1591,1337],{"emptyLinePlaceholder":1336},[1235,1593,1595],{"class":1237,"line":1594},26,[1235,1596,1337],{"emptyLinePlaceholder":1336},[1235,1598,1600,1602,1605,1608,1610,1613,1615,1618,1620,1622,1625],{"class":1237,"line":1599},27,[1235,1601,1439],{"class":1312},[1235,1603,1604],{"class":1442}," handle_get_order_status",[1235,1606,1607],{"class":1241},"(order_ref: ",[1235,1609,1449],{"class":1245},[1235,1611,1612],{"class":1241},", headers: ",[1235,1614,1455],{"class":1245},[1235,1616,1617],{"class":1241},") -> tuple[",[1235,1619,1455],{"class":1245},[1235,1621,218],{"class":1241},[1235,1623,1624],{"class":1245},"int",[1235,1626,1627],{"class":1241},"]:\n",[1235,1629,1631,1634,1636,1639,1642,1644,1647],{"class":1237,"line":1630},28,[1235,1632,1633],{"class":1241},"    token ",[1235,1635,1409],{"class":1312},[1235,1637,1638],{"class":1241}," headers.get(",[1235,1640,1641],{"class":1251},"\"X-Fibly-Verification\"",[1235,1643,218],{"class":1241},[1235,1645,1646],{"class":1251},"\"\"",[1235,1648,1428],{"class":1241},[1235,1650,1652,1655,1658],{"class":1237,"line":1651},29,[1235,1653,1654],{"class":1312},"    if",[1235,1656,1657],{"class":1312}," not",[1235,1659,1660],{"class":1241}," token:\n",[1235,1662,1664,1667,1670,1673,1675,1678,1681],{"class":1237,"line":1663},30,[1235,1665,1666],{"class":1312},"        return",[1235,1668,1669],{"class":1241}," {",[1235,1671,1672],{"class":1251},"\"error\"",[1235,1674,1153],{"class":1241},[1235,1676,1677],{"class":1251},"\"missing verification token\"",[1235,1679,1680],{"class":1241},"}, ",[1235,1682,1683],{"class":1245},"401\n",[1235,1685,1687,1690],{"class":1237,"line":1686},31,[1235,1688,1689],{"class":1312},"    try",[1235,1691,1458],{"class":1241},[1235,1693,1695,1698,1700],{"class":1237,"line":1694},32,[1235,1696,1697],{"class":1241},"        claims ",[1235,1699,1409],{"class":1312},[1235,1701,1702],{"class":1241}," verify_fibly_token(token)\n",[1235,1704,1706,1709,1712],{"class":1237,"line":1705},33,[1235,1707,1708],{"class":1312},"    except",[1235,1710,1711],{"class":1245}," Exception",[1235,1713,1458],{"class":1241},[1235,1715,1717,1719,1721,1723,1725,1728,1730],{"class":1237,"line":1716},34,[1235,1718,1666],{"class":1312},[1235,1720,1669],{"class":1241},[1235,1722,1672],{"class":1251},[1235,1724,1153],{"class":1241},[1235,1726,1727],{"class":1251},"\"invalid verification token\"",[1235,1729,1680],{"class":1241},[1235,1731,1683],{"class":1245},[1235,1733,1735],{"class":1237,"line":1734},35,[1235,1736,1337],{"emptyLinePlaceholder":1336},[1235,1738,1740,1743,1745,1748],{"class":1237,"line":1739},36,[1235,1741,1742],{"class":1241},"    order ",[1235,1744,1409],{"class":1312},[1235,1746,1747],{"class":1241}," get_order(order_ref)  ",[1235,1749,1750],{"class":1343},"# Twoje własne wyszukiwanie\n",[1235,1752,1754,1756,1759,1762,1765],{"class":1237,"line":1753},37,[1235,1755,1654],{"class":1312},[1235,1757,1758],{"class":1241}," order ",[1235,1760,1761],{"class":1312},"is",[1235,1763,1764],{"class":1245}," None",[1235,1766,1458],{"class":1241},[1235,1768,1770,1772,1774,1776,1778,1781,1783],{"class":1237,"line":1769},38,[1235,1771,1666],{"class":1312},[1235,1773,1669],{"class":1241},[1235,1775,1672],{"class":1251},[1235,1777,1153],{"class":1241},[1235,1779,1780],{"class":1251},"\"not found\"",[1235,1782,1680],{"class":1241},[1235,1784,1785],{"class":1245},"404\n",[1235,1787,1789],{"class":1237,"line":1788},39,[1235,1790,1337],{"emptyLinePlaceholder":1336},[1235,1792,1794,1797,1799,1802,1805,1808,1811,1814],{"class":1237,"line":1793},40,[1235,1795,1796],{"class":1241},"    verified_email ",[1235,1798,1409],{"class":1312},[1235,1800,1801],{"class":1241}," (claims.get(",[1235,1803,1804],{"class":1251},"\"email\"",[1235,1806,1807],{"class":1241},") ",[1235,1809,1810],{"class":1312},"or",[1235,1812,1813],{"class":1251}," \"\"",[1235,1815,1816],{"class":1241},").lower()\n",[1235,1818,1820,1822,1824,1827,1830,1832,1834,1837,1840],{"class":1237,"line":1819},41,[1235,1821,1654],{"class":1312},[1235,1823,1657],{"class":1312},[1235,1825,1826],{"class":1241}," claims.get(",[1235,1828,1829],{"class":1251},"\"email_verified\"",[1235,1831,1807],{"class":1241},[1235,1833,1810],{"class":1312},[1235,1835,1836],{"class":1241}," order.customer_email.lower() ",[1235,1838,1839],{"class":1312},"!=",[1235,1841,1842],{"class":1241}," verified_email:\n",[1235,1844,1846,1848,1850,1852,1854,1856,1858,1860],{"class":1237,"line":1845},42,[1235,1847,1666],{"class":1312},[1235,1849,1669],{"class":1241},[1235,1851,1672],{"class":1251},[1235,1853,1153],{"class":1241},[1235,1855,1780],{"class":1251},[1235,1857,1680],{"class":1241},[1235,1859,1269],{"class":1245},[1235,1861,1862],{"class":1343},"  # 404, nie 403 — nie potwierdzaj istnienia zamówienia\n",[1235,1864,1866],{"class":1237,"line":1865},43,[1235,1867,1337],{"emptyLinePlaceholder":1336},[1235,1869,1871,1873,1875,1877,1880,1882,1885],{"class":1237,"line":1870},44,[1235,1872,1583],{"class":1312},[1235,1874,1669],{"class":1241},[1235,1876,1246],{"class":1251},[1235,1878,1879],{"class":1241},": order_ref, ",[1235,1881,1257],{"class":1251},[1235,1883,1884],{"class":1241},": order.status}, ",[1235,1886,1887],{"class":1245},"200\n",[1299,1889,1890],{"v-slot:node":1201},[1193,1891,1895],{"className":1892,"code":1893,"language":1894,"meta":1201,"style":1201},"language-js shiki shiki-themes github-dark","import { createRemoteJWKSet, jwtVerify } from 'jose';\n\n\u002F\u002F Skopiuj obie wartości z panelu Klucze podpisujące tego połączenia i zaszyj je na\n\u002F\u002F stałe jako konfigurację — nigdy nie wyznaczaj JWKS_URL na podstawie roszczenia z\n\u002F\u002F (niezweryfikowanego) tokena, bo token podpisany kluczem innego tenanta mógłby się\n\u002F\u002F tu zweryfikować.\nconst JWKS_URL = new URL(\n  'https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json', \u002F\u002F skopiuj z panelu\n);\nconst CONNECTION_ID = 'c1a2e3f4-5678-4abc-9def-0123456789ab'; \u002F\u002F „ID połączenia” w panelu Klucze podpisujące\n\n\u002F\u002F createRemoteJWKSet cache'uje odpowiedź i pobiera ją ponownie przy nierozpoznanym `kid`.\nconst jwks = createRemoteJWKSet(JWKS_URL);\n\nasync function verifyFiblyToken(token) {\n  const { payload } = await jwtVerify(token, jwks, {\n    issuer: 'fibly',\n    audience: CONNECTION_ID,\n    algorithms: ['RS256'],\n  });\n  return payload;\n}\n\napp.get('\u002Forders\u002F:ref', async (req, res) => {\n  const token = req.header('X-Fibly-Verification');\n  if (!token) return res.status(401).json({ error: 'missing verification token' });\n\n  let claims;\n  try {\n    claims = await verifyFiblyToken(token);\n  } catch {\n    return res.status(401).json({ error: 'invalid verification token' });\n  }\n\n  const order = await getOrder(req.params.ref); \u002F\u002F Twoje własne wyszukiwanie\n  if (!order) return res.status(404).json({ error: 'not found' });\n\n  const verifiedEmail = (claims.email || '').toLowerCase();\n  if (!claims.email_verified || order.customerEmail.toLowerCase() !== verifiedEmail) {\n    return res.status(404).json({ error: 'not found' }); \u002F\u002F 404, nie 403\n  }\n\n  res.json({ order_ref: req.params.ref, status: order.status });\n});\n","js",[108,1896,1897,1912,1916,1921,1926,1931,1936,1955,1965,1970,1988,1992,1997,2016,2020,2039,2064,2074,2083,2093,2098,2106,2111,2115,2151,2173,2214,2218,2226,2233,2246,2256,2279,2284,2288,2308,2340,2344,2370,2397,2423,2427,2431,2441],{"__ignoreMap":1201},[1235,1898,1899,1901,1904,1906,1909],{"class":1237,"line":1238},[1235,1900,1313],{"class":1312},[1235,1902,1903],{"class":1241}," { createRemoteJWKSet, jwtVerify } ",[1235,1905,1322],{"class":1312},[1235,1907,1908],{"class":1251}," 'jose'",[1235,1910,1911],{"class":1241},";\n",[1235,1913,1914],{"class":1237,"line":1319},[1235,1915,1337],{"emptyLinePlaceholder":1336},[1235,1917,1918],{"class":1237,"line":1333},[1235,1919,1920],{"class":1343},"\u002F\u002F Skopiuj obie wartości z panelu Klucze podpisujące tego połączenia i zaszyj je na\n",[1235,1922,1923],{"class":1237,"line":1340},[1235,1924,1925],{"class":1343},"\u002F\u002F stałe jako konfigurację — nigdy nie wyznaczaj JWKS_URL na podstawie roszczenia z\n",[1235,1927,1928],{"class":1237,"line":1347},[1235,1929,1930],{"class":1343},"\u002F\u002F (niezweryfikowanego) tokena, bo token podpisany kluczem innego tenanta mógłby się\n",[1235,1932,1933],{"class":1237,"line":1353},[1235,1934,1935],{"class":1343},"\u002F\u002F tu zweryfikować.\n",[1235,1937,1938,1941,1944,1946,1949,1952],{"class":1237,"line":1359},[1235,1939,1940],{"class":1312},"const",[1235,1942,1943],{"class":1245}," JWKS_URL",[1235,1945,1370],{"class":1312},[1235,1947,1948],{"class":1312}," new",[1235,1950,1951],{"class":1442}," URL",[1235,1953,1954],{"class":1241},"(\n",[1235,1956,1957,1960,1962],{"class":1237,"line":1365},[1235,1958,1959],{"class":1251},"  'https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json'",[1235,1961,218],{"class":1241},[1235,1963,1964],{"class":1343},"\u002F\u002F skopiuj z panelu\n",[1235,1966,1967],{"class":1237,"line":1379},[1235,1968,1969],{"class":1241},");\n",[1235,1971,1972,1974,1977,1979,1982,1985],{"class":1237,"line":1392},[1235,1973,1940],{"class":1312},[1235,1975,1976],{"class":1245}," CONNECTION_ID",[1235,1978,1370],{"class":1312},[1235,1980,1981],{"class":1251}," 'c1a2e3f4-5678-4abc-9def-0123456789ab'",[1235,1983,1984],{"class":1241},"; ",[1235,1986,1987],{"class":1343},"\u002F\u002F „ID połączenia” w panelu Klucze podpisujące\n",[1235,1989,1990],{"class":1237,"line":1397},[1235,1991,1337],{"emptyLinePlaceholder":1336},[1235,1993,1994],{"class":1237,"line":1403},[1235,1995,1996],{"class":1343},"\u002F\u002F createRemoteJWKSet cache'uje odpowiedź i pobiera ją ponownie przy nierozpoznanym `kid`.\n",[1235,1998,1999,2001,2004,2006,2009,2012,2014],{"class":1237,"line":1431},[1235,2000,1940],{"class":1312},[1235,2002,2003],{"class":1245}," jwks",[1235,2005,1370],{"class":1312},[1235,2007,2008],{"class":1442}," createRemoteJWKSet",[1235,2010,2011],{"class":1241},"(",[1235,2013,475],{"class":1245},[1235,2015,1969],{"class":1241},[1235,2017,2018],{"class":1237,"line":1436},[1235,2019,1337],{"emptyLinePlaceholder":1336},[1235,2021,2022,2025,2028,2031,2033,2036],{"class":1237,"line":1461},[1235,2023,2024],{"class":1312},"async",[1235,2026,2027],{"class":1312}," function",[1235,2029,2030],{"class":1442}," verifyFiblyToken",[1235,2032,2011],{"class":1241},[1235,2034,2035],{"class":1419},"token",[1235,2037,2038],{"class":1241},") {\n",[1235,2040,2041,2044,2047,2050,2053,2055,2058,2061],{"class":1237,"line":1472},[1235,2042,2043],{"class":1312},"  const",[1235,2045,2046],{"class":1241}," { ",[1235,2048,2049],{"class":1245},"payload",[1235,2051,2052],{"class":1241}," } ",[1235,2054,1409],{"class":1312},[1235,2056,2057],{"class":1312}," await",[1235,2059,2060],{"class":1442}," jwtVerify",[1235,2062,2063],{"class":1241},"(token, jwks, {\n",[1235,2065,2066,2069,2072],{"class":1237,"line":1483},[1235,2067,2068],{"class":1241},"    issuer: ",[1235,2070,2071],{"class":1251},"'fibly'",[1235,2073,38],{"class":1241},[1235,2075,2076,2079,2081],{"class":1237,"line":1489},[1235,2077,2078],{"class":1241},"    audience: ",[1235,2080,479],{"class":1245},[1235,2082,38],{"class":1241},[1235,2084,2085,2088,2091],{"class":1237,"line":1495},[1235,2086,2087],{"class":1241},"    algorithms: [",[1235,2089,2090],{"class":1251},"'RS256'",[1235,2092,1509],{"class":1241},[1235,2094,2095],{"class":1237,"line":1512},[1235,2096,2097],{"class":1241},"  });\n",[1235,2099,2100,2103],{"class":1237,"line":1524},[1235,2101,2102],{"class":1312},"  return",[1235,2104,2105],{"class":1241}," payload;\n",[1235,2107,2108],{"class":1237,"line":1536},[1235,2109,2110],{"class":1241},"}\n",[1235,2112,2113],{"class":1237,"line":1574},[1235,2114,1337],{"emptyLinePlaceholder":1336},[1235,2116,2117,2120,2123,2125,2128,2130,2132,2135,2138,2140,2143,2145,2148],{"class":1237,"line":1580},[1235,2118,2119],{"class":1241},"app.",[1235,2121,2122],{"class":1442},"get",[1235,2124,2011],{"class":1241},[1235,2126,2127],{"class":1251},"'\u002Forders\u002F:ref'",[1235,2129,218],{"class":1241},[1235,2131,2024],{"class":1312},[1235,2133,2134],{"class":1241}," (",[1235,2136,2137],{"class":1419},"req",[1235,2139,218],{"class":1241},[1235,2141,2142],{"class":1419},"res",[1235,2144,1807],{"class":1241},[1235,2146,2147],{"class":1312},"=>",[1235,2149,2150],{"class":1241}," {\n",[1235,2152,2153,2155,2158,2160,2163,2166,2168,2171],{"class":1237,"line":1589},[1235,2154,2043],{"class":1312},[1235,2156,2157],{"class":1245}," token",[1235,2159,1370],{"class":1312},[1235,2161,2162],{"class":1241}," req.",[1235,2164,2165],{"class":1442},"header",[1235,2167,2011],{"class":1241},[1235,2169,2170],{"class":1251},"'X-Fibly-Verification'",[1235,2172,1969],{"class":1241},[1235,2174,2175,2178,2180,2183,2186,2189,2192,2195,2197,2200,2203,2205,2208,2211],{"class":1237,"line":1594},[1235,2176,2177],{"class":1312},"  if",[1235,2179,2134],{"class":1241},[1235,2181,2182],{"class":1312},"!",[1235,2184,2185],{"class":1241},"token) ",[1235,2187,2188],{"class":1312},"return",[1235,2190,2191],{"class":1241}," res.",[1235,2193,2194],{"class":1442},"status",[1235,2196,2011],{"class":1241},[1235,2198,2199],{"class":1245},"401",[1235,2201,2202],{"class":1241},").",[1235,2204,1231],{"class":1442},[1235,2206,2207],{"class":1241},"({ error: ",[1235,2209,2210],{"class":1251},"'missing verification token'",[1235,2212,2213],{"class":1241}," });\n",[1235,2215,2216],{"class":1237,"line":1599},[1235,2217,1337],{"emptyLinePlaceholder":1336},[1235,2219,2220,2223],{"class":1237,"line":1630},[1235,2221,2222],{"class":1312},"  let",[1235,2224,2225],{"class":1241}," claims;\n",[1235,2227,2228,2231],{"class":1237,"line":1651},[1235,2229,2230],{"class":1312},"  try",[1235,2232,2150],{"class":1241},[1235,2234,2235,2237,2239,2241,2243],{"class":1237,"line":1663},[1235,2236,1475],{"class":1241},[1235,2238,1409],{"class":1312},[1235,2240,2057],{"class":1312},[1235,2242,2030],{"class":1442},[1235,2244,2245],{"class":1241},"(token);\n",[1235,2247,2248,2251,2254],{"class":1237,"line":1686},[1235,2249,2250],{"class":1241},"  } ",[1235,2252,2253],{"class":1312},"catch",[1235,2255,2150],{"class":1241},[1235,2257,2258,2260,2262,2264,2266,2268,2270,2272,2274,2277],{"class":1237,"line":1694},[1235,2259,1583],{"class":1312},[1235,2261,2191],{"class":1241},[1235,2263,2194],{"class":1442},[1235,2265,2011],{"class":1241},[1235,2267,2199],{"class":1245},[1235,2269,2202],{"class":1241},[1235,2271,1231],{"class":1442},[1235,2273,2207],{"class":1241},[1235,2275,2276],{"class":1251},"'invalid verification token'",[1235,2278,2213],{"class":1241},[1235,2280,2281],{"class":1237,"line":1705},[1235,2282,2283],{"class":1241},"  }\n",[1235,2285,2286],{"class":1237,"line":1716},[1235,2287,1337],{"emptyLinePlaceholder":1336},[1235,2289,2290,2292,2295,2297,2299,2302,2305],{"class":1237,"line":1734},[1235,2291,2043],{"class":1312},[1235,2293,2294],{"class":1245}," order",[1235,2296,1370],{"class":1312},[1235,2298,2057],{"class":1312},[1235,2300,2301],{"class":1442}," getOrder",[1235,2303,2304],{"class":1241},"(req.params.ref); ",[1235,2306,2307],{"class":1343},"\u002F\u002F Twoje własne wyszukiwanie\n",[1235,2309,2310,2312,2314,2316,2319,2321,2323,2325,2327,2329,2331,2333,2335,2338],{"class":1237,"line":1739},[1235,2311,2177],{"class":1312},[1235,2313,2134],{"class":1241},[1235,2315,2182],{"class":1312},[1235,2317,2318],{"class":1241},"order) ",[1235,2320,2188],{"class":1312},[1235,2322,2191],{"class":1241},[1235,2324,2194],{"class":1442},[1235,2326,2011],{"class":1241},[1235,2328,1269],{"class":1245},[1235,2330,2202],{"class":1241},[1235,2332,1231],{"class":1442},[1235,2334,2207],{"class":1241},[1235,2336,2337],{"class":1251},"'not found'",[1235,2339,2213],{"class":1241},[1235,2341,2342],{"class":1237,"line":1753},[1235,2343,1337],{"emptyLinePlaceholder":1336},[1235,2345,2346,2348,2351,2353,2356,2359,2362,2364,2367],{"class":1237,"line":1769},[1235,2347,2043],{"class":1312},[1235,2349,2350],{"class":1245}," verifiedEmail",[1235,2352,1370],{"class":1312},[1235,2354,2355],{"class":1241}," (claims.email ",[1235,2357,2358],{"class":1312},"||",[1235,2360,2361],{"class":1251}," ''",[1235,2363,2202],{"class":1241},[1235,2365,2366],{"class":1442},"toLowerCase",[1235,2368,2369],{"class":1241},"();\n",[1235,2371,2372,2374,2376,2378,2381,2383,2386,2388,2391,2394],{"class":1237,"line":1788},[1235,2373,2177],{"class":1312},[1235,2375,2134],{"class":1241},[1235,2377,2182],{"class":1312},[1235,2379,2380],{"class":1241},"claims.email_verified ",[1235,2382,2358],{"class":1312},[1235,2384,2385],{"class":1241}," order.customerEmail.",[1235,2387,2366],{"class":1442},[1235,2389,2390],{"class":1241},"() ",[1235,2392,2393],{"class":1312},"!==",[1235,2395,2396],{"class":1241}," verifiedEmail) {\n",[1235,2398,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417,2420],{"class":1237,"line":1793},[1235,2400,1583],{"class":1312},[1235,2402,2191],{"class":1241},[1235,2404,2194],{"class":1442},[1235,2406,2011],{"class":1241},[1235,2408,1269],{"class":1245},[1235,2410,2202],{"class":1241},[1235,2412,1231],{"class":1442},[1235,2414,2207],{"class":1241},[1235,2416,2337],{"class":1251},[1235,2418,2419],{"class":1241}," }); ",[1235,2421,2422],{"class":1343},"\u002F\u002F 404, nie 403\n",[1235,2424,2425],{"class":1237,"line":1819},[1235,2426,2283],{"class":1241},[1235,2428,2429],{"class":1237,"line":1845},[1235,2430,1337],{"emptyLinePlaceholder":1336},[1235,2432,2433,2436,2438],{"class":1237,"line":1865},[1235,2434,2435],{"class":1241},"  res.",[1235,2437,1231],{"class":1442},[1235,2439,2440],{"class":1241},"({ order_ref: req.params.ref, status: order.status });\n",[1235,2442,2443],{"class":1237,"line":1870},[1235,2444,2445],{"class":1241},"});\n",[1299,2447,2448],{"v-slot:php":1201},[1193,2449,2453],{"className":2450,"code":2451,"language":2452,"meta":1201,"style":1201},"language-php shiki shiki-themes github-dark","\u003C?php\nuse Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\JWK;\n\n\u002F\u002F Skopiuj obie wartości z panelu Klucze podpisujące tego połączenia i zaszyj je na\n\u002F\u002F stałe jako konfigurację — nigdy nie wyznaczaj JWKS_URL na podstawie roszczenia z\n\u002F\u002F (niezweryfikowanego) tokena, bo token podpisany kluczem innego tenanta mógłby się\n\u002F\u002F tu zweryfikować.\nconst JWKS_URL = 'https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json'; \u002F\u002F skopiuj z panelu\nconst CONNECTION_ID = 'c1a2e3f4-5678-4abc-9def-0123456789ab'; \u002F\u002F „ID połączenia” w panelu Klucze podpisujące\n\nfunction verify_fibly_token(string $token): array\n{\n    \u002F\u002F W produkcji cache'uj tę odpowiedź zamiast pobierać ją przy każdym żądaniu.\n    $jwks = json_decode(file_get_contents(JWKS_URL), true);\n    $keys = JWK::parseKeySet($jwks);\n\n    \u002F\u002F JWT::decode weryfikuje podpis RS256 (dobierając klucz po `kid`) i\n    \u002F\u002F automatycznie egzekwuje `exp`; `iss`\u002F`aud` sprawdzamy jawnie poniżej.\n    $claims = (array) JWT::decode($token, $keys);\n\n    if (($claims['iss'] ?? null) !== 'fibly') {\n        throw new \\RuntimeException('unexpected issuer');\n    }\n    if (($claims['aud'] ?? null) !== CONNECTION_ID) {\n        throw new \\RuntimeException('unexpected audience');\n    }\n    return $claims;\n}\n\n\u002F\u002F GET \u002Forders\u002F{ref}\n$token = $_SERVER['HTTP_X_FIBLY_VERIFICATION'] ?? '';\nif ($token === '') {\n    http_response_code(401);\n    echo json_encode(['error' => 'missing verification token']);\n    exit;\n}\n\ntry {\n    $claims = verify_fibly_token($token);\n} catch (\\Throwable $e) {\n    http_response_code(401);\n    echo json_encode(['error' => 'invalid verification token']);\n    exit;\n}\n\n$order = get_order($_GET['ref'] ?? ''); \u002F\u002F Twoje własne wyszukiwanie\nif (!$order) {\n    http_response_code(404);\n    echo json_encode(['error' => 'not found']);\n    exit;\n}\n\n$verifiedEmail = strtolower($claims['email'] ?? '');\n$emailVerified = !empty($claims['email_verified']);\nif (!$emailVerified || strtolower($order['customer_email']) !== $verifiedEmail) {\n    http_response_code(404); \u002F\u002F 404, nie 403 — nie potwierdzaj istnienia zamówienia\n    echo json_encode(['error' => 'not found']);\n    exit;\n}\n\necho json_encode(['order_ref' => $order['ref'], 'status' => $order['status']]);\n","php",[108,2454,2455,2463,2473,2482,2486,2490,2494,2498,2502,2517,2531,2535,2555,2560,2565,2591,2610,2614,2619,2624,2649,2653,2681,2698,2703,2726,2741,2745,2752,2756,2760,2765,2786,2801,2812,2835,2842,2846,2850,2857,2868,2883,2893,2910,2916,2921,2926,2954,2966,2977,2995,3002,3007,3012,3037,3058,3087,3101,3118,3125,3130,3135],{"__ignoreMap":1201},[1235,2456,2457,2460],{"class":1237,"line":1238},[1235,2458,2459],{"class":1312},"\u003C?",[1235,2461,2462],{"class":1245},"php\n",[1235,2464,2465,2468,2471],{"class":1237,"line":1319},[1235,2466,2467],{"class":1312},"use",[1235,2469,2470],{"class":1245}," Firebase\\JWT\\JWT",[1235,2472,1911],{"class":1241},[1235,2474,2475,2477,2480],{"class":1237,"line":1333},[1235,2476,2467],{"class":1312},[1235,2478,2479],{"class":1245}," Firebase\\JWT\\JWK",[1235,2481,1911],{"class":1241},[1235,2483,2484],{"class":1237,"line":1340},[1235,2485,1337],{"emptyLinePlaceholder":1336},[1235,2487,2488],{"class":1237,"line":1347},[1235,2489,1920],{"class":1343},[1235,2491,2492],{"class":1237,"line":1353},[1235,2493,1925],{"class":1343},[1235,2495,2496],{"class":1237,"line":1359},[1235,2497,1930],{"class":1343},[1235,2499,2500],{"class":1237,"line":1365},[1235,2501,1935],{"class":1343},[1235,2503,2504,2506,2508,2510,2513,2515],{"class":1237,"line":1379},[1235,2505,1940],{"class":1312},[1235,2507,1943],{"class":1245},[1235,2509,1370],{"class":1312},[1235,2511,2512],{"class":1251}," 'https:\u002F\u002Fapp.fibly.io\u002Fapi\u002Ftool-integrations\u002Fcustom-webhooks\u002F\u003Cid-Twojego-obszaru-roboczego>\u002Fjwks.json'",[1235,2514,1984],{"class":1241},[1235,2516,1964],{"class":1343},[1235,2518,2519,2521,2523,2525,2527,2529],{"class":1237,"line":1392},[1235,2520,1940],{"class":1312},[1235,2522,1976],{"class":1245},[1235,2524,1370],{"class":1312},[1235,2526,1981],{"class":1251},[1235,2528,1984],{"class":1241},[1235,2530,1987],{"class":1343},[1235,2532,2533],{"class":1237,"line":1397},[1235,2534,1337],{"emptyLinePlaceholder":1336},[1235,2536,2537,2540,2542,2544,2546,2549,2552],{"class":1237,"line":1403},[1235,2538,2539],{"class":1312},"function",[1235,2541,1443],{"class":1442},[1235,2543,2011],{"class":1241},[1235,2545,538],{"class":1312},[1235,2547,2548],{"class":1241}," $token)",[1235,2550,2551],{"class":1312},":",[1235,2553,2554],{"class":1312}," array\n",[1235,2556,2557],{"class":1237,"line":1431},[1235,2558,2559],{"class":1241},"{\n",[1235,2561,2562],{"class":1237,"line":1436},[1235,2563,2564],{"class":1343},"    \u002F\u002F W produkcji cache'uj tę odpowiedź zamiast pobierać ją przy każdym żądaniu.\n",[1235,2566,2567,2570,2572,2575,2577,2580,2582,2584,2587,2589],{"class":1237,"line":1461},[1235,2568,2569],{"class":1241},"    $jwks ",[1235,2571,1409],{"class":1312},[1235,2573,2574],{"class":1245}," json_decode",[1235,2576,2011],{"class":1241},[1235,2578,2579],{"class":1245},"file_get_contents",[1235,2581,2011],{"class":1241},[1235,2583,475],{"class":1245},[1235,2585,2586],{"class":1241},"), ",[1235,2588,1055],{"class":1245},[1235,2590,1969],{"class":1241},[1235,2592,2593,2596,2598,2601,2604,2607],{"class":1237,"line":1472},[1235,2594,2595],{"class":1241},"    $keys ",[1235,2597,1409],{"class":1312},[1235,2599,2600],{"class":1245}," JWK",[1235,2602,2603],{"class":1312},"::",[1235,2605,2606],{"class":1442},"parseKeySet",[1235,2608,2609],{"class":1241},"($jwks);\n",[1235,2611,2612],{"class":1237,"line":1483},[1235,2613,1337],{"emptyLinePlaceholder":1336},[1235,2615,2616],{"class":1237,"line":1489},[1235,2617,2618],{"class":1343},"    \u002F\u002F JWT::decode weryfikuje podpis RS256 (dobierając klucz po `kid`) i\n",[1235,2620,2621],{"class":1237,"line":1495},[1235,2622,2623],{"class":1343},"    \u002F\u002F automatycznie egzekwuje `exp`; `iss`\u002F`aud` sprawdzamy jawnie poniżej.\n",[1235,2625,2626,2629,2631,2633,2636,2638,2641,2643,2646],{"class":1237,"line":1512},[1235,2627,2628],{"class":1241},"    $claims ",[1235,2630,1409],{"class":1312},[1235,2632,2134],{"class":1241},[1235,2634,2635],{"class":1312},"array",[1235,2637,1807],{"class":1241},[1235,2639,2640],{"class":1245},"JWT",[1235,2642,2603],{"class":1312},[1235,2644,2645],{"class":1442},"decode",[1235,2647,2648],{"class":1241},"($token, $keys);\n",[1235,2650,2651],{"class":1237,"line":1524},[1235,2652,1337],{"emptyLinePlaceholder":1336},[1235,2654,2655,2657,2660,2663,2666,2669,2672,2674,2676,2679],{"class":1237,"line":1536},[1235,2656,1654],{"class":1312},[1235,2658,2659],{"class":1241}," (($claims[",[1235,2661,2662],{"class":1251},"'iss'",[1235,2664,2665],{"class":1241},"] ",[1235,2667,2668],{"class":1312},"??",[1235,2670,2671],{"class":1245}," null",[1235,2673,1807],{"class":1241},[1235,2675,2393],{"class":1312},[1235,2677,2678],{"class":1251}," 'fibly'",[1235,2680,2038],{"class":1241},[1235,2682,2683,2686,2688,2691,2693,2696],{"class":1237,"line":1574},[1235,2684,2685],{"class":1312},"        throw",[1235,2687,1948],{"class":1312},[1235,2689,2690],{"class":1245}," \\RuntimeException",[1235,2692,2011],{"class":1241},[1235,2694,2695],{"class":1251},"'unexpected issuer'",[1235,2697,1969],{"class":1241},[1235,2699,2700],{"class":1237,"line":1580},[1235,2701,2702],{"class":1241},"    }\n",[1235,2704,2705,2707,2709,2712,2714,2716,2718,2720,2722,2724],{"class":1237,"line":1589},[1235,2706,1654],{"class":1312},[1235,2708,2659],{"class":1241},[1235,2710,2711],{"class":1251},"'aud'",[1235,2713,2665],{"class":1241},[1235,2715,2668],{"class":1312},[1235,2717,2671],{"class":1245},[1235,2719,1807],{"class":1241},[1235,2721,2393],{"class":1312},[1235,2723,1976],{"class":1245},[1235,2725,2038],{"class":1241},[1235,2727,2728,2730,2732,2734,2736,2739],{"class":1237,"line":1594},[1235,2729,2685],{"class":1312},[1235,2731,1948],{"class":1312},[1235,2733,2690],{"class":1245},[1235,2735,2011],{"class":1241},[1235,2737,2738],{"class":1251},"'unexpected audience'",[1235,2740,1969],{"class":1241},[1235,2742,2743],{"class":1237,"line":1599},[1235,2744,2702],{"class":1241},[1235,2746,2747,2749],{"class":1237,"line":1630},[1235,2748,1583],{"class":1312},[1235,2750,2751],{"class":1241}," $claims;\n",[1235,2753,2754],{"class":1237,"line":1651},[1235,2755,2110],{"class":1241},[1235,2757,2758],{"class":1237,"line":1663},[1235,2759,1337],{"emptyLinePlaceholder":1336},[1235,2761,2762],{"class":1237,"line":1686},[1235,2763,2764],{"class":1343},"\u002F\u002F GET \u002Forders\u002F{ref}\n",[1235,2766,2767,2770,2772,2775,2778,2780,2782,2784],{"class":1237,"line":1694},[1235,2768,2769],{"class":1241},"$token ",[1235,2771,1409],{"class":1312},[1235,2773,2774],{"class":1241}," $_SERVER[",[1235,2776,2777],{"class":1251},"'HTTP_X_FIBLY_VERIFICATION'",[1235,2779,2665],{"class":1241},[1235,2781,2668],{"class":1312},[1235,2783,2361],{"class":1251},[1235,2785,1911],{"class":1241},[1235,2787,2788,2791,2794,2797,2799],{"class":1237,"line":1705},[1235,2789,2790],{"class":1312},"if",[1235,2792,2793],{"class":1241}," ($token ",[1235,2795,2796],{"class":1312},"===",[1235,2798,2361],{"class":1251},[1235,2800,2038],{"class":1241},[1235,2802,2803,2806,2808,2810],{"class":1237,"line":1716},[1235,2804,2805],{"class":1245},"    http_response_code",[1235,2807,2011],{"class":1241},[1235,2809,2199],{"class":1245},[1235,2811,1969],{"class":1241},[1235,2813,2814,2817,2820,2823,2826,2829,2832],{"class":1237,"line":1734},[1235,2815,2816],{"class":1245},"    echo",[1235,2818,2819],{"class":1245}," json_encode",[1235,2821,2822],{"class":1241},"([",[1235,2824,2825],{"class":1251},"'error'",[1235,2827,2828],{"class":1312}," =>",[1235,2830,2831],{"class":1251}," 'missing verification token'",[1235,2833,2834],{"class":1241},"]);\n",[1235,2836,2837,2840],{"class":1237,"line":1739},[1235,2838,2839],{"class":1312},"    exit",[1235,2841,1911],{"class":1241},[1235,2843,2844],{"class":1237,"line":1753},[1235,2845,2110],{"class":1241},[1235,2847,2848],{"class":1237,"line":1769},[1235,2849,1337],{"emptyLinePlaceholder":1336},[1235,2851,2852,2855],{"class":1237,"line":1788},[1235,2853,2854],{"class":1312},"try",[1235,2856,2150],{"class":1241},[1235,2858,2859,2861,2863,2865],{"class":1237,"line":1793},[1235,2860,2628],{"class":1241},[1235,2862,1409],{"class":1312},[1235,2864,1443],{"class":1442},[1235,2866,2867],{"class":1241},"($token);\n",[1235,2869,2870,2873,2875,2877,2880],{"class":1237,"line":1819},[1235,2871,2872],{"class":1241},"} ",[1235,2874,2253],{"class":1312},[1235,2876,2134],{"class":1241},[1235,2878,2879],{"class":1245},"\\Throwable",[1235,2881,2882],{"class":1241}," $e) {\n",[1235,2884,2885,2887,2889,2891],{"class":1237,"line":1845},[1235,2886,2805],{"class":1245},[1235,2888,2011],{"class":1241},[1235,2890,2199],{"class":1245},[1235,2892,1969],{"class":1241},[1235,2894,2895,2897,2899,2901,2903,2905,2908],{"class":1237,"line":1865},[1235,2896,2816],{"class":1245},[1235,2898,2819],{"class":1245},[1235,2900,2822],{"class":1241},[1235,2902,2825],{"class":1251},[1235,2904,2828],{"class":1312},[1235,2906,2907],{"class":1251}," 'invalid verification token'",[1235,2909,2834],{"class":1241},[1235,2911,2912,2914],{"class":1237,"line":1870},[1235,2913,2839],{"class":1312},[1235,2915,1911],{"class":1241},[1235,2917,2919],{"class":1237,"line":2918},45,[1235,2920,2110],{"class":1241},[1235,2922,2924],{"class":1237,"line":2923},46,[1235,2925,1337],{"emptyLinePlaceholder":1336},[1235,2927,2929,2932,2934,2937,2940,2943,2945,2947,2949,2952],{"class":1237,"line":2928},47,[1235,2930,2931],{"class":1241},"$order ",[1235,2933,1409],{"class":1312},[1235,2935,2936],{"class":1442}," get_order",[1235,2938,2939],{"class":1241},"($_GET[",[1235,2941,2942],{"class":1251},"'ref'",[1235,2944,2665],{"class":1241},[1235,2946,2668],{"class":1312},[1235,2948,2361],{"class":1251},[1235,2950,2951],{"class":1241},"); ",[1235,2953,2307],{"class":1343},[1235,2955,2957,2959,2961,2963],{"class":1237,"line":2956},48,[1235,2958,2790],{"class":1312},[1235,2960,2134],{"class":1241},[1235,2962,2182],{"class":1312},[1235,2964,2965],{"class":1241},"$order) {\n",[1235,2967,2969,2971,2973,2975],{"class":1237,"line":2968},49,[1235,2970,2805],{"class":1245},[1235,2972,2011],{"class":1241},[1235,2974,1269],{"class":1245},[1235,2976,1969],{"class":1241},[1235,2978,2980,2982,2984,2986,2988,2990,2993],{"class":1237,"line":2979},50,[1235,2981,2816],{"class":1245},[1235,2983,2819],{"class":1245},[1235,2985,2822],{"class":1241},[1235,2987,2825],{"class":1251},[1235,2989,2828],{"class":1312},[1235,2991,2992],{"class":1251}," 'not found'",[1235,2994,2834],{"class":1241},[1235,2996,2998,3000],{"class":1237,"line":2997},51,[1235,2999,2839],{"class":1312},[1235,3001,1911],{"class":1241},[1235,3003,3005],{"class":1237,"line":3004},52,[1235,3006,2110],{"class":1241},[1235,3008,3010],{"class":1237,"line":3009},53,[1235,3011,1337],{"emptyLinePlaceholder":1336},[1235,3013,3015,3018,3020,3023,3026,3029,3031,3033,3035],{"class":1237,"line":3014},54,[1235,3016,3017],{"class":1241},"$verifiedEmail ",[1235,3019,1409],{"class":1312},[1235,3021,3022],{"class":1245}," strtolower",[1235,3024,3025],{"class":1241},"($claims[",[1235,3027,3028],{"class":1251},"'email'",[1235,3030,2665],{"class":1241},[1235,3032,2668],{"class":1312},[1235,3034,2361],{"class":1251},[1235,3036,1969],{"class":1241},[1235,3038,3040,3043,3045,3048,3051,3053,3056],{"class":1237,"line":3039},55,[1235,3041,3042],{"class":1241},"$emailVerified ",[1235,3044,1409],{"class":1312},[1235,3046,3047],{"class":1312}," !",[1235,3049,3050],{"class":1245},"empty",[1235,3052,3025],{"class":1241},[1235,3054,3055],{"class":1251},"'email_verified'",[1235,3057,2834],{"class":1241},[1235,3059,3061,3063,3065,3067,3069,3071,3073,3076,3079,3082,3084],{"class":1237,"line":3060},56,[1235,3062,2790],{"class":1312},[1235,3064,2134],{"class":1241},[1235,3066,2182],{"class":1312},[1235,3068,3042],{"class":1241},[1235,3070,2358],{"class":1312},[1235,3072,3022],{"class":1245},[1235,3074,3075],{"class":1241},"($order[",[1235,3077,3078],{"class":1251},"'customer_email'",[1235,3080,3081],{"class":1241},"]) ",[1235,3083,2393],{"class":1312},[1235,3085,3086],{"class":1241}," $verifiedEmail) {\n",[1235,3088,3090,3092,3094,3096,3098],{"class":1237,"line":3089},57,[1235,3091,2805],{"class":1245},[1235,3093,2011],{"class":1241},[1235,3095,1269],{"class":1245},[1235,3097,2951],{"class":1241},[1235,3099,3100],{"class":1343},"\u002F\u002F 404, nie 403 — nie potwierdzaj istnienia zamówienia\n",[1235,3102,3104,3106,3108,3110,3112,3114,3116],{"class":1237,"line":3103},58,[1235,3105,2816],{"class":1245},[1235,3107,2819],{"class":1245},[1235,3109,2822],{"class":1241},[1235,3111,2825],{"class":1251},[1235,3113,2828],{"class":1312},[1235,3115,2992],{"class":1251},[1235,3117,2834],{"class":1241},[1235,3119,3121,3123],{"class":1237,"line":3120},59,[1235,3122,2839],{"class":1312},[1235,3124,1911],{"class":1241},[1235,3126,3128],{"class":1237,"line":3127},60,[1235,3129,2110],{"class":1241},[1235,3131,3133],{"class":1237,"line":3132},61,[1235,3134,1337],{"emptyLinePlaceholder":1336},[1235,3136,3138,3141,3143,3145,3148,3150,3153,3155,3158,3161,3163,3165,3167],{"class":1237,"line":3137},62,[1235,3139,3140],{"class":1245},"echo",[1235,3142,2819],{"class":1245},[1235,3144,2822],{"class":1241},[1235,3146,3147],{"class":1251},"'order_ref'",[1235,3149,2828],{"class":1312},[1235,3151,3152],{"class":1241}," $order[",[1235,3154,2942],{"class":1251},[1235,3156,3157],{"class":1241},"], ",[1235,3159,3160],{"class":1251},"'status'",[1235,3162,2828],{"class":1312},[1235,3164,3152],{"class":1241},[1235,3166,3160],{"class":1251},[1235,3168,3169],{"class":1241},"]]);\n",[49,3171,3173],{"id":3172},"weryfikacja-tożsamości-i-potwierdzenie","Weryfikacja tożsamości i potwierdzenie",[16,3175,3176],{},"Dwa niezależne przełączniki, ustawiane per narzędzie, kontrolują, jak ostrożnie narzędzie jest\nwywoływane:",[385,3178,3180,3181,413],{"id":3179},"weryfikacja-tożsamości-requires_verification","Weryfikacja tożsamości (",[108,3182,3183],{},"requires_verification",[16,3185,416,3186,3188,3189,3191,3192,82],{},[20,3187,299],{}," dla narzędzia, które zwraca prywatne dane (szczegóły\nzamówienia, informacje o koncie, cokolwiek powiązanego z jednym klientem). Gdy jest włączona,\nagent może wywołać Twój webhook dopiero, gdy odwiedzający udowodni, że jest właścicielem swojego\ne-maila — albo przez własny link weryfikacyjny Fibly, albo dlatego że rozmowa przyszła kanałem\nzweryfikowanego e-maila. Do tego czasu wywołanie narzędzia zwraca modelowi status\n",[108,3190,1187],{},", który prosi klienta o weryfikację i ponawia próbę — ",[20,3193,3194],{},"Twój webhook nigdy\nnie jest wywoływany dla niezweryfikowanej próby",[16,3196,3197,3198,3201,3202,3205,3206,347,3208,3210],{},"To dowodzi jedynie, że wywołujący kontroluje ",[1140,3199,3200],{},"jakiś"," adres e-mail. ",[20,3203,3204],{},"Nie"," dowodzi, że konkretny\nżądany zasób (np. to konkretne zamówienie) należy do niego — ta weryfikacja zawsze należy do\nCiebie, na podstawie zweryfikowanych roszczeń ",[108,3207,750],{},[108,3209,810],{}," w tokenie, jak pokazano w\nprzykładzie powyżej.",[385,3212,3214,3215,413],{"id":3213},"potwierdzenie-requires_confirmation","Potwierdzenie (",[108,3216,3217],{},"requires_confirmation",[16,3219,416,3220,3222],{},[20,3221,289],{}," dla narzędzia, które coś zmienia (tworzy zgłoszenie, anuluje\nzamówienie, cokolwiek, czego nie chcesz uruchamiać po cichu). Gdy jest włączona, widget zatrzymuje\nsię i prosi klienta o wyraźne zatwierdzenie konkretnego wywołania, zanim dotrze ono do Twojego\nwebhooka. Gdy jest wyłączona, narzędzie uruchamia się natychmiast, gdy tylko model zdecyduje się\ngo użyć — odpowiednie dla odczytów bez skutków ubocznych.",[49,3224,3226],{"id":3225},"testowanie-narzędzia","Testowanie narzędzia",[16,3228,3229,3230,3233,3234,3237,3238,3241,3242,3244,3245,3247],{},"Zanim włączysz narzędzie dla prawdziwych rozmów, otwórz je w edytorze i skorzystaj z panelu\n",[20,3231,3232],{},"Przetestuj to narzędzie",": wprowadź przykładowe argumenty jako JSON, a następnie kliknij\n",[20,3235,3236],{},"Uruchom test",". Wysyła to ",[20,3239,3240],{},"prawdziwe"," wywołanie dokładnie tą samą ścieżką, którą przechodzi\nruch produkcyjny — sprawdzone pod kątem SSRF, z dołączonym rzeczywistym tokenem\n",[108,3243,156],{},", jeśli ustawienie połączenia ",[20,3246,152],{}," jest włączone\n— i pokazuje zwrócony status oraz odpowiedź od razu w panelu, dzięki czemu możesz potwierdzić, że\nwebhook jest poprawnie podłączony, zanim go włączysz.",[49,3249,3251],{"id":3250},"lista-kontrolna-bezpieczeństwa","Lista kontrolna bezpieczeństwa",[93,3253,3254,3263,3271,3277,3290,3296,3302],{},[70,3255,3256,3259,3260,3262],{},[20,3257,3258],{},"Zawsze weryfikuj podpis."," Nigdy nie ufaj roszczeniom w ",[108,3261,156],{},", dopóki podpis\nRS256 nie zostanie potwierdzony względem Twojego JWKS.",[70,3264,3265,3270],{},[20,3266,3267,3268,82],{},"Sprawdzaj ",[108,3269,623],{}," Odrzucaj wygasłe tokeny; większość bibliotek JWT robi to automatycznie po\ndekodowaniu z weryfikacją.",[70,3272,3273,3276],{},[20,3274,3275],{},"Sam egzekwuj własność zasobu."," Fibly potwierdza, kim jest zweryfikowany odwiedzający; nie zna\nTwojego modelu danych, więc nie może potwierdzić, że rekord, o który pyta, do niego należy.",[70,3278,3279,3284,3285,3287,3288,82],{},[20,3280,3281,3282,82],{},"Nie ufaj samemu ",[108,3283,750],{}," Traktuj go jako zweryfikowany dopiero, gdy ",[108,3286,766],{}," ma\nwartość ",[108,3289,1055],{},[70,3291,3292,3295],{},[20,3293,3294],{},"Używaj HTTPS"," na swoim endpoincie — Fibly tego wymaga (poza własnym środowiskiem deweloperskim\nobszaru roboczego, które i tak nie jest dostępne z internetu).",[70,3297,3298,3301],{},[20,3299,3300],{},"Chroń sekret swojego połączenia."," Traktuj dane Basic\u002FBearer jak hasło; Fibly szyfruje je w\nspoczynku i nigdy nie wyświetla ponownie po zapisaniu.",[70,3303,3304,3307],{},[20,3305,3306],{},"Preferuj 404 zamiast 403",", gdy weryfikacja własności się nie powiedzie, aby nie potwierdzać\nwywołującemu, że dany zasób w ogóle istnieje.",[49,3309,3311],{"id":3310},"powiązane-artykuły","Powiązane artykuły",[93,3313,3314,3321],{},[70,3315,3316,3320],{},[34,3317,3319],{"href":3318},"\u002Fpomoc\u002Fnarzedzia","Przegląd narzędzi",": wszystkie narzędzia, z których może korzystać bot.",[70,3322,3323,3327],{},[34,3324,3326],{"href":3325},"\u002Fpomoc\u002Frozmowy","Rozmowy",": zobacz akcje wykonane przez bota, w tym wywołania narzędzi\nniestandardowych.",[3329,3330,3331],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":1201,"searchDepth":1319,"depth":1319,"links":3333},[3334,3335,3336,3337,3340,3349,3350,3356,3357,3358],{"id":51,"depth":1319,"text":52},{"id":58,"depth":1319,"text":59},{"id":178,"depth":1319,"text":179},{"id":320,"depth":1319,"text":321,"children":3338},[3339],{"id":387,"depth":1333,"text":388},{"id":409,"depth":1319,"text":3341,"children":3342},"Weryfikacja wywołującego (X-Fibly-Verification)",[3343,3344,3345,3347,3348],{"id":435,"depth":1333,"text":436},{"id":491,"depth":1333,"text":492},{"id":876,"depth":1333,"text":3346},"Dane kanału (channel_data)",{"id":1068,"depth":1333,"text":1069},{"id":1146,"depth":1333,"text":1147},{"id":1273,"depth":1319,"text":1274},{"id":3172,"depth":1319,"text":3173,"children":3351},[3352,3354],{"id":3179,"depth":1333,"text":3353},"Weryfikacja tożsamości (requires_verification)",{"id":3213,"depth":1333,"text":3355},"Potwierdzenie (requires_confirmation)",{"id":3225,"depth":1319,"text":3226},{"id":3250,"depth":1319,"text":3251},{"id":3310,"depth":1319,"text":3311},"Zamień własne API HTTP w narzędzia agenta — zbuduj połączenia i narzędzia w panelu, a następnie zweryfikuj podpisane żądanie na swoim serwerze.","md","tools\u002Fcustom-webhook-tools",{},"\u002Fpomoc\u002Fnarzedzia\u002Fwlasne-webhooki",{"title":5,"description":3359},"pomoc\u002Fnarzedzia\u002Fwlasne-webhooki","Y7AkBLYLRiF0yaRW819GKX-5x-sEggX6-ag1VxBRvUQ",[3368,3373,3376,3382,3385,3390,3395,3400,3405,3410,3415,3420,3425,3430,3435,3440,3445,3450,3455,3460,3465,3470,3475,3480,3485,3488,3493,3498,3503,3508,3513,3518,3523,3528,3533,3538,3543,3548,3549,3554,3559,3564,3569,3574,3579,3584,3589,3594,3599,3604,3609,3614,3619,3624,3629,3634,3639,3644,3649,3654,3659,3664,3669,3674,3678,3681,3686,3691,3696,3701,3706,3712],{"path":3369,"title":3370,"description":3371,"order":3372,"key":3372},"\u002Fpomoc\u002Fzespol-i-konto\u002Fdwuetapowe-uwierzytelnianie","Dwuetapowe uwierzytelnianie","[object Object]",null,{"path":3374,"title":3375,"description":3371,"order":3372,"key":3372},"\u002Fpomoc\u002Frozmowy\u002Fszczegoly-rozmowy","Szczegóły rozmowy",{"path":3377,"title":3378,"description":3379,"order":3380,"key":3381},"\u002Fpomoc","Centrum pomocy Fibly","Przewodniki, instrukcje i odpowiedzi na pytania dotyczące konfiguracji oraz codziennej pracy z Fibly.",0,"index",{"path":36,"title":37,"description":3383,"order":1238,"key":3384},"Podłącz Calendly, aby bot mógł sprawdzać dostępność, udostępniać linki do rezerwacji i umawiać spotkania w trakcie rozmowy.","tools\u002Fcalendly",{"path":3386,"title":3387,"description":3388,"order":1238,"key":3389},"\u002Fpomoc\u002Fzespol-i-konto\u002Fczlonkowie-zespolu","Członkowie zespołu","Jak zaprosić, edytować i usunąć użytkownika w panelu Fibly.","team-and-account\u002Fteam-members",{"path":3391,"title":3392,"description":3393,"order":1238,"key":3394},"\u002Fpomoc\u002Fkanaly\u002Femail","E-mail","Podłącz swoje skrzynki wsparcia do Fibly przez IMAP i SMTP, żeby przychodząca poczta stawała się zgłoszeniami, na które odpowiada bot i Twój zespół.","channels\u002Femail",{"path":3396,"title":3397,"description":3398,"order":1238,"key":3399},"\u002Fpomoc\u002Finstalacja\u002Fwordpress","Instalacja na WordPressie","Trzy sposoby na dodanie widgetu Fibly do witryny opartej o WordPress.","installation\u002Fwordpress",{"path":3401,"title":3402,"description":3403,"order":1238,"key":3404},"\u002Fpomoc\u002Fwprowadzenie\u002Fjak-dziala-bot","Jak działa bot Fibly","Przegląd architektury, od pytania klienta po przekazanie sprawy do zespołu.","getting-started\u002Fhow-the-bot-works",{"path":3406,"title":3407,"description":3408,"order":1238,"key":3409},"\u002Fpomoc\u002Frozmowy\u002Flista-i-filtry","Lista i filtry","Jak filtrować, sortować i znajdować rozmowy w panelu Fibly.","conversations\u002Flist-and-filters",{"path":3411,"title":3412,"description":3413,"order":1238,"key":3414},"\u002Fpomoc\u002Fklienci\u002Flista-klientow","Lista klientów","Jak przeglądać, filtrować i wyszukiwać klientów w panelu Fibly.","customers\u002Fcustomer-list",{"path":3416,"title":3417,"description":3418,"order":1238,"key":3419},"\u002Fpomoc\u002Fkonfiguracja-bota\u002Fmarka","Marka","Jak ustawić adres strony i krótki opis marki, czyli dwa pola, których bot Fibly używa jako podstawowego kontekstu.","bot-configuration\u002Fbrand",{"path":3421,"title":3422,"description":3423,"order":1238,"key":3424},"\u002Fpomoc\u002Frozliczenia\u002Fplany","Plany","Porównanie planów Starter, Professional i Enterprise w Fibly oraz dostępne dodatki.","billing\u002Fplans",{"path":3426,"title":3427,"description":3428,"order":1238,"key":3429},"\u002Fpomoc\u002Fwsparcie-na-zywo\u002Fprzejmowanie-rozmowy","Przejmowanie rozmowy","Jak przejąć rozmowę od bota i prowadzić ją osobiście jako konsultant.","live-support\u002Ftaking-over-a-conversation",{"path":3431,"title":3432,"description":3433,"order":1238,"key":3434},"\u002Fpomoc\u002Fanalityka\u002Fstrona-glowna","Strona główna","Co pokazują kafelki metryk i wykresy na ekranie startowym panelu Fibly.","analytics\u002Foverview",{"path":3436,"title":3437,"description":3438,"order":1238,"key":3439},"\u002Fpomoc\u002Frozwiazywanie-problemow\u002Fwidget-sie-nie-pojawia","Widget się nie pojawia","Co sprawdzić, gdy po osadzeniu skryptu na stronie nie widać przycisku czatu.","troubleshooting\u002Fwidget-not-appearing",{"path":3441,"title":3442,"description":3443,"order":1238,"key":3444},"\u002Fpomoc\u002Fwidget\u002Fwyglad","Wygląd widgetu","Jak dopasować kolory, tekst przycisku i tytuł okna czatu do swojej marki.","widget\u002Fappearance",{"path":3446,"title":3447,"description":3448,"order":1319,"key":3449},"\u002Fpomoc\u002Frozwiazywanie-problemow\u002Fbot-daje-bledne-odpowiedzi","Bot daje błędne odpowiedzi","Co zrobić, gdy bot odpowiada nieprecyzyjnie, miesza fakty albo zmyśla.","troubleshooting\u002Fbot-gives-wrong-answers",{"path":3451,"title":3452,"description":3453,"order":1319,"key":3454},"\u002Fpomoc\u002Fanalityka\u002Fcentrum-sterowania","Centrum Sterowania","Zaawansowana analityka eskalacji, rozkład pewności bota i rekomendacje w panelu Fibly.","analytics\u002Fcontrol-center",{"path":3456,"title":3457,"description":3458,"order":1319,"key":3459},"\u002Fpomoc\u002Fbaza-wiedzy\u002Fimport-markdown","Import plików Markdown","Jak zaimportować istniejącą dokumentację w formacie Markdown do bazy wiedzy Fibly.","knowledge-base\u002Fimport-markdown",{"path":3461,"title":3462,"description":3463,"order":1319,"key":3464},"\u002Fpomoc\u002Finstalacja\u002Fshopify","Instalacja na Shopify","Jak dodać widget Fibly do sklepu Shopify przez edycję pliku theme.liquid.","installation\u002Fshopify",{"path":3466,"title":3467,"description":3468,"order":1319,"key":3469},"\u002Fpomoc\u002Fwsparcie-na-zywo\u002Fkonczenie-rozmowy","Kończenie rozmowy","Jak oddać rozmowę z powrotem botowi lub zamknąć ją z wynikiem rozwiązania.","live-support\u002Fending-a-conversation",{"path":3471,"title":3472,"description":3473,"order":1319,"key":3474},"\u002Fpomoc\u002Frozliczenia\u002Fkredyty-i-uzycie","Kredyty i użycie","Co to są kredyty AI, ile zużywa pojedyncza wiadomość bota i gdzie sprawdzisz aktualne wykorzystanie.","billing\u002Fcredits-and-usage",{"path":3476,"title":3477,"description":3478,"order":1319,"key":3479},"\u002Fpomoc\u002Fwprowadzenie\u002Fpierwsze-logowanie","Pierwsze logowanie","Jak zaakceptować zaproszenie do Fibly i uzyskać dostęp do panelu administracyjnego.","getting-started\u002Ffirst-login",{"path":3481,"title":3482,"description":3483,"order":1319,"key":3484},"\u002Fpomoc\u002Fwidget\u002Fpowiadomienie-powitalne","Powiadomienie powitalne","Jak ustawić krótką wiadomość, która zachęca klienta do otwarcia czatu.","widget\u002Fwelcome-notification",{"path":41,"title":42,"description":3486,"order":1319,"key":3487},"Podłącz PrestaShop, aby bot mógł sprawdzać status zamówień, szczegóły produktów i stany magazynowe dla Twoich klientów w trakcie rozmowy.","tools\u002Fprestashop",{"path":3489,"title":3490,"description":3491,"order":1319,"key":3492},"\u002Fpomoc\u002Fklienci\u002Fprofil-klienta","Profil klienta","Jak edytować dane klienta, dodawać notatki, przeglądać historię rozmów oraz anonimizować dane zgodnie z RODO.","customers\u002Fcustomer-profile",{"path":3494,"title":3495,"description":3496,"order":1319,"key":3497},"\u002Fpomoc\u002Fzespol-i-konto\u002Frole-i-uprawnienia","Role i uprawnienia","Co może Administrator, Menadżer i Agent w panelu Fibly.","team-and-account\u002Froles-and-permissions",{"path":3499,"title":3500,"description":3501,"order":1319,"key":3502},"\u002Fpomoc\u002Fkanaly\u002Fwhatsapp","WhatsApp","Podłącz swój numer WhatsApp Business, żeby Fibly odpowiadał klientom na WhatsAppie, a każda rozmowa trafiała do tej samej skrzynki.","channels\u002Fwhatsapp",{"path":3504,"title":3505,"description":3506,"order":1319,"key":3507},"\u002Fpomoc\u002Fkonfiguracja-bota\u002Fwiadomosci","Wiadomości","Jak ustawić pierwszą wiadomość bota i wybrać jeden z trzech charakterów wypowiedzi.","bot-configuration\u002Fmessages",{"path":3509,"title":3510,"description":3511,"order":1333,"key":3512},"\u002Fpomoc\u002Fwidget\u002Fdzwiek-powiadomien","Dźwięk powiadomień","Jak wybrać sygnał dźwiękowy, który widget odgrywa klientowi przy nowych wiadomościach.","widget\u002Fnotification-sound",{"path":3514,"title":3515,"description":3516,"order":1333,"key":3517},"\u002Fpomoc\u002Fkanaly\u002Fmessenger","Facebook Messenger","Podłącz swoje strony na Facebooku, żeby Fibly odpowiadał na wiadomości w Messengerze — w tej samej skrzynce co pozostałe kanały.","channels\u002Fmessenger",{"path":3519,"title":3520,"description":3521,"order":1333,"key":3522},"\u002Fpomoc\u002Finstalacja\u002Fwix","Instalacja na Wix","Jak dodać widget Fibly do witryny w Wix przez panel ustawień strony.","installation\u002Fwix",{"path":3524,"title":3525,"description":3526,"order":1333,"key":3527},"\u002Fpomoc\u002Frozliczenia\u002Fmiejsca-w-zespole","Miejsca w zespole","Co oznacza limit miejsc, jak dokupić dodatkowe oraz co stanie się po przekroczeniu limitu.","billing\u002Fteam-seats",{"path":3529,"title":3530,"description":3531,"order":1333,"key":3532},"\u002Fpomoc\u002Fzespol-i-konto\u002Fprofil-uzytkownika","Profil użytkownika","Jak zmienić imię, nazwisko i sprawdzić swoje dane konta w panelu Fibly.","team-and-account\u002Fuser-profile",{"path":3534,"title":3535,"description":3536,"order":1333,"key":3537},"\u002Fpomoc\u002Fbaza-wiedzy\u002Frecznie-pisany-artykul","Ręczne pisanie artykułów","Jak pisać artykuły bazy wiedzy w edytorze Fibly, w trybie wizualnym lub źródłowym.","knowledge-base\u002Fmanually-written-article",{"path":3539,"title":3540,"description":3541,"order":1333,"key":3542},"\u002Fpomoc\u002Fwprowadzenie\u002Fszybki-start","Szybki start","Lista kontrolna pierwszego uruchomienia bota, od logowania po pierwszą rozmowę.","getting-started\u002Fquick-start",{"path":3544,"title":3545,"description":3546,"order":1333,"key":3547},"\u002Fpomoc\u002Fkonfiguracja-bota\u002Fwsparcie-czlowieka","Wsparcie człowieka","Jak skonfigurować przekazywanie rozmów do zespołu, gdy bot nie radzi sobie z pytaniem.","bot-configuration\u002Fhuman-support",{"path":3363,"title":5,"description":3359,"order":1333,"key":3361},{"path":3550,"title":3551,"description":3552,"order":1333,"key":3553},"\u002Fpomoc\u002Frozmowy\u002Fzamykanie-rozmowy","Zamykanie rozmowy","Jak oznaczać zakończone rozmowy jako rozwiązane lub nierozwiązane i dlaczego ma to znaczenie.","conversations\u002Fclosing-a-conversation",{"path":3555,"title":3556,"description":3557,"order":1340,"key":3558},"\u002Fpomoc\u002Frozmowy\u002Fai-asysta","Asysta AI dla konsultanta","Jak wygenerować szkic odpowiedzi opartej na bazie wiedzy podczas obsługi rozmowy.","conversations\u002Fai-assist",{"path":3560,"title":3561,"description":3562,"order":1340,"key":3563},"\u002Fpomoc\u002Frozwiazywanie-problemow\u002Fbrak-powiadomien-mailowych","Brak powiadomień e-mailowych","Co sprawdzić, gdy nie otrzymujesz e-maili o eskalacjach albo tygodniowego podsumowania.","troubleshooting\u002Fno-email-notifications",{"path":3565,"title":3566,"description":3567,"order":1340,"key":3568},"\u002Fpomoc\u002Frozliczenia\u002Ffaktury","Faktury","Gdzie znajdziesz faktury, jakie mają statusy płatności i jak pobrać PDF.","billing\u002Finvoices",{"path":3570,"title":3571,"description":3572,"order":1340,"key":3573},"\u002Fpomoc\u002Fkanaly\u002Finstagram","Instagram","Podłącz swoje konto Instagram Professional, żeby Fibly odpowiadał na wiadomości prywatne na Instagramie — z jednej skrzynki.","channels\u002Finstagram",{"path":3575,"title":3576,"description":3577,"order":1340,"key":3578},"\u002Fpomoc\u002Finstalacja\u002Fprestashop","Instalacja na PrestaShop","Jak zainstalować oficjalny moduł Fibly w sklepie PrestaShop.","installation\u002Fprestashop",{"path":3580,"title":3581,"description":3582,"order":1340,"key":3583},"\u002Fpomoc\u002Fkonfiguracja-bota\u002Fkontekst-bazy-wiedzy","Kontekst bazy wiedzy","Jak ustawić głębokość wymagań wstępnych, którą bot bierze pod uwagę przy odpowiedzi.","bot-configuration\u002Fknowledge-base-context",{"path":3585,"title":3586,"description":3587,"order":1340,"key":3588},"\u002Fpomoc\u002Fbaza-wiedzy\u002Fprzypinanie-artykulow","Przypinanie artykułów","Jak wybrać do trzech kluczowych artykułów, które bot Fibly czyta przed każdą odpowiedzią.","knowledge-base\u002Fpinning-articles",{"path":3590,"title":3591,"description":3592,"order":1340,"key":3593},"\u002Fpomoc\u002Fwidget\u002Fwlaczanie-i-wylaczanie","Włączanie i wyłączanie widgetu","Jak tymczasowo ukryć przycisk czatu, bez usuwania kodu ze strony.","widget\u002Fenabling-and-disabling",{"path":3595,"title":3596,"description":3597,"order":1340,"key":3598},"\u002Fpomoc\u002Fzespol-i-konto\u002Fzmiana-hasla","Zmiana hasła","Jak zaktualizować hasło do swojego konta Fibly.","team-and-account\u002Fchanging-password",{"path":3600,"title":3601,"description":3602,"order":1347,"key":3603},"\u002Fpomoc\u002Finstalacja\u002Fsquarespace","Instalacja na Squarespace","Jak osadzić widget Fibly w witrynie Squarespace przez sekcję „Code Injection\".","installation\u002Fsquarespace",{"path":3605,"title":3606,"description":3607,"order":1347,"key":3608},"\u002Fpomoc\u002Frozwiazywanie-problemow\u002Frozmowa-nie-w-wsparciu-na-zywo","Rozmowa nie pojawia się we Wsparciu na żywo","Diagnostyka sytuacji, w której klient prosi o człowieka, ale rozmowa nie trafia do kolejki konsultanta.","troubleshooting\u002Fconversation-not-in-live-support",{"path":3610,"title":3611,"description":3612,"order":1347,"key":3613},"\u002Fpomoc\u002Fbaza-wiedzy\u002Fwymagania-wstepne","Wymagania wstępne","Jak łączyć artykuły bazy wiedzy w grupy, które bot Fibly czyta razem.","knowledge-base\u002Fprerequisites",{"path":3615,"title":3616,"description":3617,"order":1347,"key":3618},"\u002Fpomoc\u002Frozliczenia\u002Fzmiana-planu","Zmiana planu","Jak przejść na wyższy lub niższy plan w Fibly.","billing\u002Fchanging-plan",{"path":3620,"title":3621,"description":3622,"order":1353,"key":3623},"\u002Fpomoc\u002Finstalacja\u002Fwlasna-strona","Instalacja na własnej stronie","Jak osadzić widget Fibly w czystym HTML-u, Next.js, Nuxt, Vue i React.","installation\u002Fcustom-website",{"path":3625,"title":3626,"description":3627,"order":1353,"key":3628},"\u002Fpomoc\u002Fbaza-wiedzy\u002Fjakosc-tresci","Jakość treści","Jak Fibly automatycznie ocenia artykuły bazy wiedzy i co oznaczają poszczególne statusy.","knowledge-base\u002Fcontent-quality",{"path":3630,"title":3631,"description":3632,"order":1353,"key":3633},"\u002Fpomoc\u002Fzespol-i-konto\u002Ftygodniowe-podsumowanie","Tygodniowe podsumowanie","Cotygodniowy e-mail z metrykami pracy bota i sugestiami ulepszeń.","team-and-account\u002Fweekly-summary",{"path":3635,"title":3636,"description":3637,"order":1353,"key":3638},"\u002Fpomoc\u002Finstalacja\u002Fweryfikacja-domeny","Weryfikacja domeny","Jak potwierdzić, że jesteś właścicielem domeny, na której osadzasz widget Fibly.","installation\u002Fdomain-verification",{"path":3640,"title":3641,"description":3642,"order":1359,"key":3643},"\u002Fpomoc\u002Fbaza-wiedzy\u002Fnajlepsze-praktyki","Najlepsze praktyki","Wskazówki dotyczące pisania, organizacji i utrzymania bazy wiedzy bota Fibly.","knowledge-base\u002Fbest-practices",{"path":3645,"title":3646,"description":3647,"order":1359,"key":3648},"\u002Fpomoc\u002Finstalacja\u002Fweryfikacja-instalacji","Weryfikacja instalacji","Jak sprawdzić, że widget Fibly działa poprawnie po osadzeniu na stronie.","installation\u002Finstallation-verification",{"path":3650,"title":3651,"description":3652,"order":1392,"key":3653},"\u002Fpomoc\u002Fwprowadzenie","Wprowadzenie","Co to jest Fibly, jak działa bot i co musisz przygotować przed pierwszym logowaniem.","getting-started\u002Findex",{"path":3655,"title":3656,"description":3657,"order":1512,"key":3658},"\u002Fpomoc\u002Finstalacja","Instalacja widgetu","Jak osadzić widget Fibly na stronie. Gotowe instrukcje dla najpopularniejszych platform.","installation\u002Findex",{"path":3660,"title":3661,"description":3662,"order":1589,"key":3663},"\u002Fpomoc\u002Fwidget","Widget","Jak dostosować wygląd, treść i zachowanie widgetu czatu na Twojej stronie.","widget\u002Findex",{"path":3665,"title":3666,"description":3667,"order":1630,"key":3668},"\u002Fpomoc\u002Fkanaly","Kanały","Podłącz Fibly do miejsc, w których klienci już do Ciebie piszą — czat na stronie, e-mail, WhatsApp, Facebook Messenger i Instagram — i odpowiadaj na wszystko z jednej skrzynki.","channels\u002Findex",{"path":3670,"title":3671,"description":3672,"order":1663,"key":3673},"\u002Fpomoc\u002Fbaza-wiedzy","Baza wiedzy","Jak budować i utrzymywać bazę wiedzy, z której bot Fibly czerpie odpowiedzi.","knowledge-base\u002Findex",{"path":3318,"title":3675,"description":3676,"order":1694,"key":3677},"Narzędzia","Podłącz narzędzia, aby bot mógł wykonywać akcje w trakcie rozmowy — na przykład sprawdzać dostępność i umawiać spotkania przez Calendly.","tools\u002Findex",{"path":3325,"title":3326,"description":3679,"order":1734,"key":3680},"Jak przeglądać, filtrować i analizować rozmowy klientów z botem oraz Twoim zespołem.","conversations\u002Findex",{"path":3682,"title":3683,"description":3684,"order":1793,"key":3685},"\u002Fpomoc\u002Fkonfiguracja-bota","Konfiguracja bota","Jak ustawić markę, ton wypowiedzi, sposób eskalacji i kontekst odpowiedzi bota Fibly.","bot-configuration\u002Findex",{"path":3687,"title":3688,"description":3689,"order":2918,"key":3690},"\u002Fpomoc\u002Fwsparcie-na-zywo","Wsparcie na żywo","Jak obsługiwać rozmowy oczekujące na konsultanta, przejmować je od bota i kończyć.","live-support\u002Findex",{"path":3692,"title":3693,"description":3694,"order":2979,"key":3695},"\u002Fpomoc\u002Fanalityka","Analityka","Jak czytać metryki i wykresy dotyczące pracy bota oraz Twojego zespołu w panelu Fibly.","analytics\u002Findex",{"path":3697,"title":3698,"description":3699,"order":3039,"key":3700},"\u002Fpomoc\u002Fklienci","Klienci","Jak przeglądać i zarządzać profilami osób, które rozmawiały z botem na Twojej stronie.","customers\u002Findex",{"path":3702,"title":3703,"description":3704,"order":3127,"key":3705},"\u002Fpomoc\u002Fzespol-i-konto","Zespół i konto","Jak zarządzać członkami zespołu, rolami, własnym profilem oraz bezpieczeństwem dostępu.","team-and-account\u002Findex",{"path":3707,"title":3708,"description":3709,"order":3710,"key":3711},"\u002Fpomoc\u002Frozliczenia","Rozliczenia","Jak działają plany, kredyty AI, miejsca w zespole i faktury w Fibly.",65,"billing\u002Findex",{"path":3713,"title":3714,"description":3715,"order":3716,"key":3717},"\u002Fpomoc\u002Frozwiazywanie-problemow","Rozwiązywanie problemów","Diagnostyka najczęstszych problemów z widgetem i panelem Fibly.",999,"troubleshooting\u002Findex",1785505718264]