✨ Świeża dostawa•nowe kody na kinetyka.pl: Gemini Pro 18 mies. 170 zł•Cursor, ElevenLabs, Lovable i więcej, roczne plany AI w ułamku ceny Zobacz →
Przejdź do treści
Artykuły

Webhook: co to jest i jak połączyć AI z formularzem, mailem i arkuszem

Czym jest webhook i jak go użyć z AI: działający serwer w Pythonie, test na trzech zgłoszeniach, zabezpieczenie sekretem i wersje w Make i Zapier.

10 min czytania
Logo FastAPI - webhook z formularza połączony z AI

👁 116 przeczytań

// w skrócie
  • Webhook to adres URL, pod który zewnętrzna aplikacja wysyła dane HTTP POST od razu po zdarzeniu, zamiast czekać na cykliczne odpytywanie co kilka minut.
  • Opisany serwer oparty na FastAPI i modelu openai/gpt-5.6-luna przetwarza jedno zgłoszenie w 1,7-2,1 s przy koszcie około 0,00016 USD.
  • W Zapierze webhooki są dostępne dopiero w planach płatnych od 19,99 USD miesięcznie (przy rozliczeniu rocznym), a plan darmowy pozwala na 100 zadań miesięcznie i tylko dwukrokowe Zapy.

Webhook to adres URL, pod który jedna aplikacja sama wysyła dane do drugiej w chwili, gdy coś się wydarzy: ktoś wypełnił formularz, przyszedł mail, ktoś zapłacił. Zamiast co minutę pytać „czy jest coś nowego?”, czekasz, aż ktoś zapuka. Poniżej pokazuję webhook w praktyce: lokalny serwer w Pythonie (FastAPI) odbiera zgłoszenie z formularza, model AI je klasyfikuje i pisze szkic odpowiedzi, a wynik trafia do arkusza. Potem to samo opisuję w Make i Zapier. Tekst jest częścią ścieżki Agenci AI od zera, etap automatyzacji.

Stan na 4 października 2026

  • Test: Windows 11, Python 3.13, FastAPI 0.142.2, uvicorn 0.54.0, model openai/gpt-5.6-luna przez OpenRouter.
  • Jedno zgłoszenie: 1,7-2,1 s od wysłania do odpowiedzi, koszt około 0,00016 USD.
  • Make: plan darmowy to 1000 kredytów miesięcznie i 2 aktywne scenariusze. Zapier: 100 zadań miesięcznie, tylko Zapy dwukrokowe, a webhooki są w planach płatnych (od 19,99 USD miesięcznie przy płatności rocznej).
  • Kod: paczka promptowy-agenci-starter, pliki 06_webhook.py i 06_test_webhook.py.

Webhook, prostymi słowami

Są dwa sposoby, żeby program dowiedział się o czymś nowym:

  • pytanie co jakiś czas (polling): Twój program co 5 minut zagląda do skrzynki albo arkusza i sprawdza, czy coś przybyło. Proste, ale opóźnione i marnuje zapytania;
  • webhook: dajesz innej aplikacji swój adres (np. https://twojadomena.pl/webhook/formularz), a ona wysyła tam zapytanie HTTP POST z danymi w JSON od razu, gdy coś się stanie.

Webhook to zwykłe zapytanie do API, tylko w odwrotną stronę: to nie Ty wołasz serwis, to serwis woła Ciebie. Jeśli zapytania HTTP i JSON to dla Ciebie nowość, zacznij od przewodnika po API.

Typowe źródła webhooków:

  • formularze (Tally, Typeform, Formularze Google przez skrypt, formularz na WordPressie);
  • płatności (Stripe, PayU, Przelewy24 powiadamiają o zapłacie);
  • sklepy (WooCommerce, Shopify: nowe zamówienie);
  • narzędzia do pracy (GitHub, Slack, Trello, Calendly);
  • automatyzacje (Make, Zapier i n8n mają gotowe moduły „odbierz webhook”).

Co zbudowałem

  1. Formularz kontaktowy wysyła JSON: imię, e-mail, wiadomość.
  2. Mój serwer sprawdza sekret w nagłówku (żeby obcy nie mogli wysyłać śmieci).
  3. Model AI dostaje wiadomość i zwraca JSON: kategoria, pilność od 1 do 3, streszczenie, szkic odpowiedzi.
  4. Serwer dopisuje wiersz do pliku CSV (lokalny odpowiednik arkusza Google) i odsyła wynik.

Kod serwera webhooka

Instalacja: pip install fastapi uvicorn openai python-dotenv. W pliku .env klucz OPENROUTER_API_KEY i WEBHOOK_SECRET (długi losowy ciąg).

"""06 - Webhook: formularz wysyła zgłoszenie -> serwer pyta model -> wynik trafia do arkusza (CSV) i wraca w odpowiedzi.
Start:  uvicorn 06_webhook:app --port 8000      (albo: python 06_webhook.py)
Test:   curl -X POST http://127.0.0.1:8000/webhook/formularz -H "X-Webhook-Secret: ..." -H "Content-Type: application/json"
             -d "{\"imie\":\"Ola\",\"email\":\"[email protected]\",\"wiadomosc\":\"Faktura ma zły NIP\"}"
"""
import csv, datetime, json, os, pathlib
from dotenv import load_dotenv
from fastapi import FastAPI, Header, HTTPException
from openai import OpenAI
from pydantic import BaseModel

load_dotenv()
SEKRET = os.getenv("WEBHOOK_SECRET", "zmien-mnie")       # ten sam ciąg wpisujesz w Make/Zapier/formularzu
MODEL = os.getenv("MODEL", "openai/gpt-5.6-luna")
ARKUSZ = pathlib.Path("zgloszenia.csv")
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])
app = FastAPI()

class Zgloszenie(BaseModel):          # tak wygląda JSON, który wysyła formularz
    imie: str
    email: str
    wiadomosc: str

@app.post("/webhook/formularz")
def odbierz(z: Zgloszenie, x_webhook_secret: str = Header(default="")):
    if x_webhook_secret != SEKRET:     # bez tego każdy, kto zna adres, może wysyłać Ci śmieci i palić tokeny
        raise HTTPException(status_code=401, detail="zły sekret")
    r = client.chat.completions.create(model=MODEL, response_format={"type": "json_object"}, messages=[
        {"role": "system", "content": "Jesteś asystentem biura obsługi. Zwróć JSON z polami: kategoria (faktury|reklamacja|"
         "oferta|inne), pilnosc (1-3, 3 = pilne), streszczenie (max 12 słów), szkic_odpowiedzi (2-3 zdania, po polsku, na Ty)."},
        {"role": "user", "content": f"Od: {z.imie}\nWiadomość: {z.wiadomosc}"}])
    wynik = json.loads(r.choices[0].message.content)
    nowy = not ARKUSZ.exists()
    with ARKUSZ.open("a", newline="", encoding="utf-8-sig") as f:   # utf-8-sig: Excel poprawnie pokaże polskie znaki
        w = csv.writer(f, delimiter=";")
        if nowy: w.writerow(["czas", "imie", "email", "kategoria", "pilnosc", "streszczenie", "szkic_odpowiedzi"])
        w.writerow([datetime.datetime.now().isoformat(timespec="seconds"), z.imie, z.email, wynik.get("kategoria"),
                    wynik.get("pilnosc"), wynik.get("streszczenie"), wynik.get("szkic_odpowiedzi")])
    return {"ok": True, **wynik, "koszt_usd": getattr(r.usage, "cost", None)}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)

Kluczowe miejsca:

  • class Zgloszenie(BaseModel) opisuje, jak ma wyglądać JSON. FastAPI samo odrzuci zapytanie bez wymaganych pól (błąd 422), zanim zapłacisz za model;
  • sekret w nagłówku X-Webhook-Secret. Zgadnięty adres bez sekretu dostaje 401 i nie kosztuje nic;
  • response_format={"type": "json_object"} każe modelowi oddać czysty JSON, który od razu wpisuję w kolumny;
  • utf-8-sig przy zapisie CSV sprawia, że Excel pokazuje polskie znaki bez kombinowania.

Uruchomienie i test

W jednym oknie terminala startuję serwer: uvicorn 06_webhook:app --port 8000. W drugim uruchamiam skrypt, który udaje formularz i wysyła trzy zgłoszenia plus jedno z błędnym sekretem:

"""Wysyła 3 przykładowe zgłoszenia do lokalnego webhooka (tak samo zrobiłby to formularz albo Make/Zapier)."""
import os, time, requests
URL = "http://127.0.0.1:8000/webhook/formularz"
SEKRET = os.getenv("WEBHOOK_SECRET", "zmien-mnie")
print("zły sekret ->", requests.post(URL, json={"imie": "X", "email": "[email protected]", "wiadomosc": "test"},
                                     headers={"X-Webhook-Secret": "zgaduje"}).status_code)
for imie, tresc in [("Ola", "Dzień dobry, na fakturze FV/2026/09/027 jest zły NIP mojej firmy. Potrzebuję korekty do piątku, bo zamykam miesiąc."),
                    ("Marek", "Ile kosztuje wdrożenie chatbota na stronę sklepu z 300 produktami? Interesuje mnie termin na listopad."),
                    ("Kasia", "Zamówiony kabel przyszedł uszkodzony, wtyczka jest pęknięta. Chcę zwrot pieniędzy.")]:
    t = time.time()
    r = requests.post(URL, json={"imie": imie, "email": f"{imie.lower()}@example.com", "wiadomosc": tresc},
                      headers={"X-Webhook-Secret": SEKRET}, timeout=60)
    print(f"\n{imie}: {tresc}\n-> HTTP {r.status_code} w {time.time() - t:.1f} s: {r.json()}")

Wynik z 4 października, 14:11:

> python 06_test_webhook.py
zły sekret -> 401

Ola: Dzień dobry, na fakturze FV/2026/09/027 jest zły NIP mojej firmy. Potrzebuję korekty do piątku, bo zamykam miesiąc.
-> HTTP 200 w 2.1 s: {'ok': True, 'kategoria': 'faktury', 'pilnosc': 3, 'streszczenie': 'Błędny NIP na fakturze, potrzebna korekta do piątku', 'szkic_odpowiedzi': 'Dzięki za wiadomość - sprawdzimy fakturę FV/2026/09/027 i przygotujemy korektę z prawidłowym NIP-em. Zajmiemy się tym pilnie, aby dokument był gotowy do piątku.', 'koszt_usd': 0.0001746}

Marek: Ile kosztuje wdrożenie chatbota na stronę sklepu z 300 produktami? Interesuje mnie termin na listopad.
-> HTTP 200 w 1.8 s: {'ok': True, 'kategoria': 'oferta', 'pilnosc': 2, 'streszczenie': 'Zapytanie o koszt i termin wdrożenia chatbota dla sklepu', 'szkic_odpowiedzi': 'Cześć Marku, przygotujemy wycenę wdrożenia chatbota dla sklepu z 300 produktami oraz sprawdzimy dostępność terminu w listopadzie. Podeślij proszę adres sklepu i napisz, jakie funkcje chatbot powinien obsługiwać.', 'koszt_usd': 0.000162}

Kasia: Zamówiony kabel przyszedł uszkodzony, wtyczka jest pęknięta. Chcę zwrot pieniędzy.
-> HTTP 200 w 1.7 s: {'ok': True, 'kategoria': 'reklamacja', 'pilnosc': 2, 'streszczenie': 'Uszkodzony kabel, pęknięta wtyczka; klientka chce zwrot pieniędzy.', 'szkic_odpowiedzi': 'Przykro nam, że kabel dotarł uszkodzony. Prześlij proszę zdjęcia uszkodzenia oraz numer zamówienia, a zajmiemy się zwrotem pieniędzy.', 'koszt_usd': 0.0001504}

> type zgloszenia.csv
czas;imie;email;kategoria;pilnosc;streszczenie;szkic_odpowiedzi
2026-10-04T14:11:16;Ola;[email protected];faktury;3;Błędny NIP na fakturze, potrzebna korekta do piątku;Dzięki za wiadomość - sprawdzimy fakturę FV/2026/09/027 i przygotujemy korektę z prawidłowym NIP-em. Zajmiemy się tym pilnie, aby dokument był gotowy do piątku.
2026-10-04T14:11:18;Marek;[email protected];oferta;2;Zapytanie o koszt i termin wdrożenia chatbota dla sklepu;Cześć Marku, przygotujemy wycenę wdrożenia chatbota dla sklepu z 300 produktami oraz sprawdzimy dostępność terminu w listopadzie. Podeślij proszę adres sklepu i napisz, jakie funkcje chatbot powinien obsługiwać.
2026-10-04T14:11:19;Kasia;[email protected];reklamacja;2;"Uszkodzony kabel, pęknięta wtyczka; klientka chce zwrot pieniędzy.";Przykro nam, że kabel dotarł uszkodzony. Prześlij proszę zdjęcia uszkodzenia oraz numer zamówienia, a zajmiemy się zwrotem pieniędzy.

Co widać:

  • zapytanie ze złym sekretem odbite kodem 401, bez wywołania modelu;
  • kategorie trafione we wszystkich trzech przypadkach. Pilność 3 dostała tylko sprawa z terminem („do piątku”), reszta 2;
  • szkice odpowiedzi są poprawne, a w reklamacji model sam poprosił o zdjęcia i numer zamówienia;
  • model raz wstawił do szkicu długi myślnik zamiast zwykłego. Jeśli masz zasady stylu, dopisz je do polecenia systemowego.

Pułapka, na którą trafiłem: curl w Git Bash na Windows z polskimi znakami wpisanymi w -d '...' wysłał zepsute kodowanie i serwer odpowiadał „There was an error parsing the body” (400). Pomogło zapisanie JSON-a do pliku i wysłanie go przez --data-binary @plik.json albo skrypt w Pythonie jak wyżej.

Jak wystawić webhook do internetu

Mam to spisane w całości

Zebrałem te rzeczy w ebookach, które możesz pobrać za darmo - bez zapisu na listę, bez haczyka.

Pobierz ebooki

Serwer na 127.0.0.1 widzi tylko Twój komputer. Żeby formularz z internetu mógł do niego zapukać, potrzebujesz publicznego adresu:

  • do testów: tunel typu ngrok albo Cloudflare Tunnel, który daje tymczasowy adres HTTPS kierujący na Twój port 8000;
  • na stałe: mały serwer albo platforma do aplikacji, np. Railway, gdzie wrzucasz ten sam plik i dostajesz adres;
  • bez serwera: odbierz webhook w Make, Zapier albo n8n (opis niżej) i z nich zawołaj model.

Zawsze używaj HTTPS i sekretu. Poważne serwisy (Stripe, GitHub) dodatkowo podpisują każde zapytanie kluczem HMAC. Wtedy zamiast porównywać sekret, liczysz podpis treści i porównujesz z nagłówkiem.

To samo w Make (bez kodu)

  1. Utwórz scenariusz i jako pierwszy moduł dodaj Webhooks, Custom webhook. Make wygeneruje adres URL.
  2. Wklej adres w ustawieniach formularza (Tally, Typeform, WordPress) i wyślij jedno testowe zgłoszenie. Make sam rozpozna strukturę JSON.
  3. Dodaj moduł AI: OpenAI (albo moduł HTTP do OpenRouter) z poleceniem jak w moim kodzie i odpowiedzią w JSON.
  4. Dodaj JSON, Parse JSON, żeby rozbić odpowiedź na pola.
  5. Dodaj Google Sheets, Add a row i przypisz pola do kolumn.
  6. Opcjonalnie: filtr „pilnosc = 3” i moduł wysyłający powiadomienie.

Każde zgłoszenie zużyje w Make kilka kredytów (po jednym na moduł). Plan darmowy daje 1000 kredytów miesięcznie i 2 aktywne scenariusze. Więcej o Make w tekście Make: jak działa i za co płacisz.

To samo w Zapier

  1. Trigger: Webhooks by Zapier, Catch Hook (adres do wklejenia w formularz). Alternatywnie gotowy trigger formularza, jeśli Zapier go obsługuje.
  2. Akcja: ChatGPT albo AI by Zapier z poleceniem klasyfikacji.
  3. Akcja: Google Sheets, Create Spreadsheet Row.

Webhooks by Zapier to aplikacja premium, więc potrzebujesz planu płatnego (Professional od 19,99 USD miesięcznie przy płatności rocznej, 29,99 USD przy miesięcznej), a cały Zap ma 3 kroki, czyli więcej niż pozwala plan darmowy. Porównanie Zapier, Make i n8n jest w tekście Zapier: co to jest i ile kosztuje.

Kod, Make czy Zapier: co wybrać

SposóbKoszt stałyCzego wymagaDla kogo
Własny serwer (FastAPI)hosting, od 0 zł na własnym komputerze z tunelempodstaw Pythonachcesz rozumieć, co się dzieje, i nie płacić za kroki
n8n (własny serwer)darmowa edycja Community, płacisz za serwerpostawienia n8n, np. na VPSdużo automatyzacji, dane u siebie
Makeod 0 USD (1000 kredytów)tylko przeglądarkiśrednio złożone scenariusze, rozgałęzienia
Zapierwebhooki od planu Professionaltylko przeglądarkinajwięcej gotowych integracji, najprostszy start

Najczęstsze pytania

Webhook co to jest w prostych słowach?

Adres internetowy, pod który inna aplikacja automatycznie wysyła informację, że coś się wydarzyło, razem z danymi tego zdarzenia.

Czym się różni webhook od API?

API to drzwi, do których Ty pukasz, kiedy czegoś potrzebujesz. Webhook to dzwonek, który dzwoni u Ciebie, kiedy coś się wydarzy po drugiej stronie. Technicznie webhook jest zapytaniem do Twojego API.

Czy webhook jest bezpieczny?

Tak bezpieczny, jak go zabezpieczysz. Minimum to HTTPS i sekret w nagłówku. Lepiej: podpis HMAC, sprawdzanie znacznika czasu (ochrona przed powtórzeniem) i ograniczenie rozmiaru danych.

Jak przetestować webhook bez publicznego serwera?

Wyślij zapytanie z własnego skryptu na 127.0.0.1 (jak w tym tekście) albo użyj tunelu, który przekieruje publiczny adres na Twój komputer.

Co się stanie, jeśli mój serwer będzie wyłączony?

Zależy od nadawcy. Stripe czy GitHub ponawiają próby przez jakiś czas. Prosty formularz może zgłoszenie zgubić. Dlatego serwer webhooka powinien odpowiadać szybko, a cięższą pracę (np. wołanie modelu) przy dużym ruchu robić w tle.

Czy mogę połączyć webhook z agentem AI?

Tak, to typowy sposób uruchamiania agentów: zdarzenie przychodzi webhookiem, a zamiast jednego zapytania do modelu startuje pętla agenta z narzędziami. Jak ją zbudować, pokazuję w tekście Jak zbudować agenta AI w Pythonie.

Google · Twoje źródłaPromptowy wyżej w Twoim Google - jednym kliknięciemDodaj do preferowanych źródeł →

Źródła i data sprawdzenia

// Newsletter

Cały tydzień w AI, w jednym mailu

Wybrane premiery, narzędzia i analizy. Raz w tygodniu, prosto do skrzynki.

Zapisz się za darmo →
Za darmo. Wypisujesz się jednym kliknięciem.
// czytaj też

Podobne tematy na Promptowym

Piotr Olszewski

Piotr Olszewski

AUTOR I WYDAWCA

Piotr Olszewski - twórca i autor Promptowego, polskiego serwisu o sztucznej inteligencji. Codziennie śledzi premiery modeli, narzędzia i regulacje AI, i tłumaczy je prostym, konkretnym językiem.

// mapa strony

🛒 Sklep Kinetyka Google AI Gemini Pro 170 zł CapCut Pro 460 zł/rok Lovable Pro 400 zł/rok Zobacz wszystko →
promptowy w liczbach 0tekstów w archiwum0newsów z ostatnich 7 dni0modeli wideo w obserwatorium0zagadek w grach
× ‹ powiększenie ›