Guides

Hvad er en webhook? Sådan giver apps besked til hinanden

En webhook er en automatisk besked, som én tjeneste sender til din app, i det øjeblik noget sker. Når en kundes betaling lykkes, sender Stripe en webhook til en adresse i din app med beskeden "betaling lykkedes, her er detaljerne", og din app reagerer — markerer ordren som betalt, sender en kvittering, låser en konto op. Kort sagt: et API er din app, der stiller et spørgsmål til en anden tjeneste; en webhook er den anden tjeneste, der ringer til din app for at fortælle noget.

Hvorfor det betyder noget, når du bygger med AI

Så snart din app tager betalinger, modtager formularindsendelser fra et andet værktøj eller forbinder sig til tjenester som GitHub, Shopify eller en kalender, støder du på webhooks. De er typisk den rigtige måde at vide, at noget er sket — men det er også der, AI-byggede apps oftest er subtilt forkerte:

  • Endpointet accepterer enhver forespørgsel, så hvem som helst kan forfalske en "betaling lykkedes"-begivenhed.
  • Appen giver adgang på betalingssidens redirect i stedet for via webhooken, så folk, der lukker fanen for tidligt, aldrig får det, de har betalt for, mens folk, der finder succes-URL'en, får det gratis.
  • Den samme begivenhed kommer to gange, og kunden får to ordrer eller to mails.

Når du ved, hvordan webhooks virker, kan du bede om beskyttelserne på forhånd.

En hverdagsanalogi: en leveringssms

Du kan finde ud af, om din pakke er kommet, på to måder. Du kan gå hen til hoveddøren hvert tiende minut for at tjekke (det er polling — din app kalder gentagne gange et API for at spørge "er der noget nyt?"). Eller kureren kan sende dig en sms, når den er leveret (det er en webhook).

Sms'en er klart bedre — så længe du kan stole på den. Hvis hvem som helst kunne sende dig en "pakke leveret"-besked, ville du gerne have en måde at vide, at den virkelig kom fra kureren. Og hvis din telefon var slukket, da sms'en kom, ville du gerne have, at kureren prøvede igen senere. De to forhold — verificering og nye forsøg — er det meste af det, der gør webhooks vanskelige.

Sådan virker en webhook, trin for trin

  1. Du opretter et endpoint i din apps backend: en URL som https://yourapp.com/webhooks/stripe, der accepterer POST-forespørgsler.
  2. Du registrerer den URL hos udbyderen og vælger, hvilke begivenheder du vil have (fx "checkout gennemført" og "abonnement annulleret").
  3. Udbyderen giver dig en signeringshemmelighed. Du gemmer den som en hemmelighed på din server — se miljøvariabler og hemmeligheder.
  4. En begivenhed sker. Udbyderen sender en HTTP-forespørgsel til din URL med en JSON-body, der beskriver begivenheden, plus en signaturheader.
  5. Din app verificerer signaturen, noterer begivenhedens ID, svarer hurtigt med en succeskode (200) og udfører først derefter arbejdet.
  6. Hvis din app ikke svarer med succes, prøver mange udbydere igen senere.

Signaturer

En signatur beviser, at forespørgslen kom fra udbyderen, og at den ikke er ændret. Stripe beregner for eksempel en HMAC (en slags nøglet fingeraftryk) med SHA-256 over request-body'en og et tidsstempel, ved hjælp af signeringshemmeligheden, og sender den i en Stripe-Signature-header. Din app laver den samme beregning med sin kopi af hemmeligheden; hvis resultaterne matcher, er forespørgslen ægte. Fordi tidsstemplet også er signeret, kan du afvise gamle forespørgsler, som nogen har optaget og afspiller senere — Stripes biblioteker har som standard en tolerance på fem minutter, ifølge dokumentationen fra september 2026.

Et praktisk detalje: signaturen beregnes over den rå request-body. Hvis dit framework parser og omformaterer JSON, før du verificerer, fejler kontrollen. Det er en meget almindelig fejl.

Nye forsøg, dubletter og rækkefølge

Udbydere er forskellige, så tjek hver enkelt udbyders dokumentation. Fra september 2026:

AdfærdStripeGitHub
Automatiske nye forsøgJa, i op til tre dage med stigende intervaller i live-tilstandNej; du leverer fejlede leveringer igen manuelt eller via script
SvartidSvar hurtigt med en 2xx, før noget langsomt arbejdeEn levering, der tager mere end 10 sekunder at besvare, tæller som fejlet

Stripes dokumentation siger også, at begivenheder ikke er garanteret at ankomme i den rækkefølge, de skete, og at den samme begivenhed lejlighedsvis kan ankomme mere end én gang, så den anbefaler at følge begivenheders ID'er.

Den generelle lektie gælder for enhver udbyder: begivenheder kan komme sent, flere gange og i en forkert rækkefølge. Din handler bør være idempotent — at behandle den samme begivenhed to gange har samme effekt som at behandle den én gang.

Et eksempel: at låse et betalt kursus op

Du sælger et onlinekursus. En studerende klikker på Køb, betaler på Stripes hostede checkout-side og sendes tilbage til dit site.

Den skrøbelige måde: "tak"-siden låser kurset op. Hvis den studerende lukker browseren under redirecten, har vedkommende betalt, men har ingen adgang. Hvis nogen gætter tak-URL'en, får de adgang uden at betale.

Webhook-måden:

  1. Når Stripe bekræfter betalingen, sender den en checkout.session.completed-begivenhed til /webhooks/stripe.
  2. Din backend verificerer signaturen med signeringshemmeligheden. Hvis den fejler, svarer den 400 og gør ingenting.
  3. Den tjekker, om begivenhedens ID allerede er behandlet. Hvis ja, svarer den 200 og stopper.
  4. Den gemmer begivenhedens ID, svarer 200, og giver derefter den studerende adgang og sender en velkomstmail.
  5. Tak-siden siger blot "Betaling modtaget — dit kursus vises om et øjeblik" og tjekker den studerendes adgangsstatus.

Senere, hvis et abonnement annulleres, eller et kort afvises, fortæller andre webhook-begivenheder din app, at den skal fjerne eller sætte adgang på pause. Sådan holder abonnementsprodukter sig i takt med faktureringen — se hvad SaaS er og sådan tilføjer du betalinger til din app.

Centrale begreber

  • Endpoint: URL'en i din app, der modtager webhooks.
  • Begivenhed / payload: hvad der skete, og de data, der beskriver det (typisk JSON).
  • Signeringshemmelighed: den delte hemmelighed, der bruges til at verificere signaturer.
  • Idempotent: sikkert at køre mere end én gang med samme resultat.
  • Polling: gentagne gange at spørge et API om ændringer i stedet for at vente på en webhook.
  • Tunnel: et værktøj, der giver en laptop en midlertidig offentlig URL, så webhooks kan nå den under udvikling.

Almindelige fejl og misforståelser

  • Ikke at verificere signaturer. Endpoint-URL'en er ikke en hemmelighed. Verificeringen er det, der gør forespørgslen troværdig.
  • At lave langsomt arbejde, før du svarer. At sende mails eller generere PDF'er, før du svarer, kan give timeouts, som udløser nye forsøg, som giver dubletter.
  • At antage præcis én gang, i rækkefølge. Gem begivenheders ID'er, og stol ikke på ankomstrækkefølgen.
  • At bruge en preview-URL. Webhooks har brug for en stabil, offentlig adresse. Private previews og localhost kan ikke nås fra internettet; brug din publicerede URL (eller en tunnel under test).
  • At blande test- og live-hemmeligheder. Udbydere udsteder ofte forskellige signeringshemmeligheder til test- og live-tilstand. Gem begge og brug den rigtige.
  • At stole blindt på payload'en i vigtige beslutninger. Ved handlinger med høje indsatser er det fornuftigt at hente den seneste tilstand fra udbyderens API, efter du har modtaget begivenheden.

Hvad du skal bede din AI-builder om

Tilføj et POST /webhooks/stripe-endpoint på serveren. Verificér Stripe-signaturen ud fra den rå request-body og hemmeligheden STRIPE_WEBHOOK_SECRET. Afvis ugyldige signaturer med 400. Gem hver begivenheds ID, og spring begivenheder over, der allerede er behandlet. Svar 200 hurtigt, og håndtér derefter checkout.session.completed ved at markere ordren som betalt og sende kvitteringen. Log begivenhedstypen. Giv ikke adgang fra checkoutens successide.

Test derefter: send en testbegivenhed fra udbyderens dashboard, send den samme igen, og send en forespørgsel med en forkert signatur. Kun den første bør ændre noget.

Webhooks på Mythex

Mythex kører ikke en separat webhook-tjeneste; du beder agenten om at tilføje et webhook-endpoint i din apps egen backend og peger udbyderen på din publicerede URL, da webhooks har brug for en offentlig adresse. Signeringshemmeligheden lægges i dine projekthemmeligheder, og hvis du ændrer den på en live app, publicerer du igen. Docs-opskriften om håndtering af webhooks har en startprompt, og skabeloner til butikker er et godt udgangspunkt for apps, der tager betalinger.

Spørgsmål

Hvad er en webhook i enkle termer?

En webhook er en automatisk besked, som én tjeneste sender til en webadresse i din app, når noget sker, fx at en betaling lykkes, eller at en formular bliver indsendt. I stedet for at din app gentagne gange spørger, om noget har ændret sig, siger den anden tjeneste det til den.

Hvad er forskellen på en webhook og en API?

Med et API-kald spørger din app en anden tjeneste om noget og får et svar. Med en webhook kalder den anden tjeneste din app, når en begivenhed sker. Mange integrationer bruger begge: webhooks til at høre om begivenheder, API-kald til at hente detaljer eller udføre handlinger.

Er webhooks sikre?

Det kan de være, hvis du verificerer dem. Gode udbydere signerer hver webhook med en hemmelighed, der kun deles med dig, og din app bør afvise enhver forespørgsel, hvis signatur ikke matcher. Uden den kontrol kan enhver, der finder URL'en, sende falske begivenheder.

Hvad sker der, hvis min app er nede, når en webhook sendes?

Det afhænger af udbyderen. Stripe prøver for eksempel fejlede leveringer igen i op til tre dage i live-tilstand, mens GitHub ikke prøver automatisk og forventer, at du leverer igen. Tjek hver udbyders dokumentation, og byg din handler, så den kan håndtere sene eller gentagne begivenheder.

Mythex · Pricing · Byg hvad som helst med AI · Skabeloner til websites og apps · Mythex sammenlignet · Ordliste for app-bygning med AI · Gratis værktøjer til app-bygning med AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)