[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-encore-encore-webhook":3,"mdc--2p887u-key":40,"related-repo-encore-encore-webhook":1776,"related-org-encore-encore-webhook":1877},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":27,"repoUrl":28,"updatedAt":29,"license":30,"forks":31,"topics":32,"repo":35,"sourceUrl":38,"mdContent":39},"encore-webhook","receive webhooks in Encore.ts","Receive inbound webhooks from external services (Stripe, GitHub, Slack, Twilio, etc.) using `api.raw(...)` from `encore.dev\u002Fapi`. The right skill any time the user names a third-party provider that POSTs events to a URL you own.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"encore","Encore","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fencore.png","encoredev",[13,17,20,23,24],{"name":14,"slug":15,"type":16},"Backend","backend","tag",{"name":18,"slug":19,"type":16},"Integrations","integrations",{"name":21,"slug":22,"type":16},"TypeScript","typescript",{"name":9,"slug":8,"type":16},{"name":25,"slug":26,"type":16},"Webhooks","webhooks",26,"https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills","2026-05-16T06:00:00.871253",null,5,[33,34],"claude-code","skills",{"repoUrl":28,"stars":27,"forks":31,"topics":36,"description":37},[33,34],"Agent Skills for development with Encore.","https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills\u002Ftree\u002FHEAD\u002Fencore\u002Fwebhook","---\nname: encore-webhook\ndescription: Receive inbound webhooks from external services (Stripe, GitHub, Slack, Twilio, etc.) using `api.raw(...)` from `encore.dev\u002Fapi`. The right skill any time the user names a third-party provider that POSTs events to a URL you own.\nwhen_to_use: >-\n  User mentions a webhook, a \u002Fwebhooks\u002F* path, raw HTTP, `api.raw()`, accepting external callbacks, verifying webhook signatures (Stripe-Signature, X-Hub-Signature-256), reading the raw request body, parsing form-encoded payloads, or any time the user names a third-party provider that posts events — Stripe, GitHub, GitLab, Bitbucket, Shopify, Twilio, SendGrid, Mailgun, Auth0, Clerk, Slack, Discord, PayPal, Square. Use `encore-api` instead for typed JSON endpoints in your own service. Trigger phrases: \"Stripe webhook\", \"GitHub webhook\", \"\u002Fwebhooks\u002Fstripe\", \"raw HTTP endpoint\", \"api.raw\", \"verify the signature\", \"inbound webhook\", \"external callback\".\n---\n\n# Encore Webhook Endpoints\n\n## Instructions\n\nUse `api.raw(...)` to receive inbound webhooks from third-party services. Raw endpoints give you direct access to the Node.js-style request and response objects, which you need for signature verification (the verification typically requires the unparsed raw body).\n\n### 1. Import\n\n```typescript\nimport { api } from \"encore.dev\u002Fapi\";\n```\n\n### 2. Define the endpoint with `api.raw`\n\n```typescript\nexport const stripeWebhook = api.raw(\n  { expose: true, path: \"\u002Fwebhooks\u002Fstripe\", method: \"POST\" },\n  async (req, res) => {\n    const sig = req.headers[\"stripe-signature\"];\n    \u002F\u002F Read raw body\n    const chunks: Buffer[] = [];\n    for await (const chunk of req) chunks.push(chunk);\n    const rawBody = Buffer.concat(chunks).toString(\"utf8\");\n\n    \u002F\u002F Verify signature, parse event...\n\n    res.writeHead(200, { \"Content-Type\": \"application\u002Fjson\" });\n    res.end(JSON.stringify({ received: true }));\n  }\n);\n```\n\n### 3. Verify the signature\n\nMost providers sign webhooks. Read the secret with `secret(...)` from `encore.dev\u002Fconfig` (see the `encore-secret` skill) and verify before trusting the payload:\n\n```typescript\nimport { secret } from \"encore.dev\u002Fconfig\";\nconst stripeWebhookSecret = secret(\"StripeWebhookSecret\");\n\n\u002F\u002F inside handler:\nimport Stripe from \"stripe\";\nconst stripe = new Stripe(stripeApiKey());\nconst event = stripe.webhooks.constructEvent(rawBody, sig, stripeWebhookSecret());\n```\n\nFor GitHub, verify the HMAC-SHA256 in the `X-Hub-Signature-256` header against the raw body using your webhook secret.\n\n## Common providers\n\n| Provider | Signature header | Verification |\n|---|---|---|\n| Stripe | `Stripe-Signature` | `stripe.webhooks.constructEvent(rawBody, sig, secret)` |\n| GitHub | `X-Hub-Signature-256` | HMAC-SHA256 over the raw body |\n| Slack | `X-Slack-Signature` | HMAC-SHA256 over `v0:{timestamp}:{rawBody}` |\n| Shopify | `X-Shopify-Hmac-Sha256` | HMAC-SHA256 (base64) over the raw body |\n| Twilio | `X-Twilio-Signature` | HMAC-SHA1 over URL + sorted form fields |\n\n## Always respond quickly\n\nWebhook senders retry on non-2xx or slow responses. Acknowledge with a 2xx as soon as the payload is verified, then enqueue the actual work via Pub\u002FSub (see `encore-pubsub`) instead of doing it in the request handler.\n\n```typescript\nimport { Topic } from \"encore.dev\u002Fpubsub\";\n\ninterface StripeEvent { id: string; type: string; data: unknown; }\nconst stripeEvents = new Topic\u003CStripeEvent>(\"stripe-events\", {\n  deliveryGuarantee: \"at-least-once\",\n});\n\n\u002F\u002F inside the raw handler, after verification:\nawait stripeEvents.publish({ id: event.id, type: event.type, data: event.data });\nres.writeHead(200); res.end();\n```\n\n## Guidelines\n\n- Use `api.raw` *only* for webhooks and other low-level HTTP integrations.\n- Always verify the provider's signature before trusting the payload.\n- Always respond 2xx fast — push slow work onto Pub\u002FSub.\n- Store the signing secret with `secret(...)`; never inline it.\n- For typed JSON endpoints in your own service, use plain `api(...)` from the `encore-api` skill.\n",{"data":41,"body":43},{"name":4,"description":6,"when_to_use":42},"User mentions a webhook, a \u002Fwebhooks\u002F* path, raw HTTP, `api.raw()`, accepting external callbacks, verifying webhook signatures (Stripe-Signature, X-Hub-Signature-256), reading the raw request body, parsing form-encoded payloads, or any time the user names a third-party provider that posts events — Stripe, GitHub, GitLab, Bitbucket, Shopify, Twilio, SendGrid, Mailgun, Auth0, Clerk, Slack, Discord, PayPal, Square. Use `encore-api` instead for typed JSON endpoints in your own service. Trigger phrases: \"Stripe webhook\", \"GitHub webhook\", \"\u002Fwebhooks\u002Fstripe\", \"raw HTTP endpoint\", \"api.raw\", \"verify the signature\", \"inbound webhook\", \"external callback\".",{"type":44,"children":45},"root",[46,55,62,77,84,149,161,796,802,831,1084,1097,1103,1255,1261,1274,1697,1703,1770],{"type":47,"tag":48,"props":49,"children":51},"element","h1",{"id":50},"encore-webhook-endpoints",[52],{"type":53,"value":54},"text","Encore Webhook Endpoints",{"type":47,"tag":56,"props":57,"children":59},"h2",{"id":58},"instructions",[60],{"type":53,"value":61},"Instructions",{"type":47,"tag":63,"props":64,"children":65},"p",{},[66,68,75],{"type":53,"value":67},"Use ",{"type":47,"tag":69,"props":70,"children":72},"code",{"className":71},[],[73],{"type":53,"value":74},"api.raw(...)",{"type":53,"value":76}," to receive inbound webhooks from third-party services. Raw endpoints give you direct access to the Node.js-style request and response objects, which you need for signature verification (the verification typically requires the unparsed raw body).",{"type":47,"tag":78,"props":79,"children":81},"h3",{"id":80},"_1-import",[82],{"type":53,"value":83},"1. Import",{"type":47,"tag":85,"props":86,"children":90},"pre",{"className":87,"code":88,"language":22,"meta":89,"style":89},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { api } from \"encore.dev\u002Fapi\";\n","",[91],{"type":47,"tag":69,"props":92,"children":93},{"__ignoreMap":89},[94],{"type":47,"tag":95,"props":96,"children":99},"span",{"class":97,"line":98},"line",1,[100,106,112,118,123,128,133,139,144],{"type":47,"tag":95,"props":101,"children":103},{"style":102},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[104],{"type":53,"value":105},"import",{"type":47,"tag":95,"props":107,"children":109},{"style":108},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[110],{"type":53,"value":111}," {",{"type":47,"tag":95,"props":113,"children":115},{"style":114},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[116],{"type":53,"value":117}," api",{"type":47,"tag":95,"props":119,"children":120},{"style":108},[121],{"type":53,"value":122}," }",{"type":47,"tag":95,"props":124,"children":125},{"style":102},[126],{"type":53,"value":127}," from",{"type":47,"tag":95,"props":129,"children":130},{"style":108},[131],{"type":53,"value":132}," \"",{"type":47,"tag":95,"props":134,"children":136},{"style":135},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[137],{"type":53,"value":138},"encore.dev\u002Fapi",{"type":47,"tag":95,"props":140,"children":141},{"style":108},[142],{"type":53,"value":143},"\"",{"type":47,"tag":95,"props":145,"children":146},{"style":108},[147],{"type":53,"value":148},";\n",{"type":47,"tag":78,"props":150,"children":152},{"id":151},"_2-define-the-endpoint-with-apiraw",[153,155],{"type":53,"value":154},"2. Define the endpoint with ",{"type":47,"tag":69,"props":156,"children":158},{"className":157},[],[159],{"type":53,"value":160},"api.raw",{"type":47,"tag":85,"props":162,"children":164},{"className":87,"code":163,"language":22,"meta":89,"style":89},"export const stripeWebhook = api.raw(\n  { expose: true, path: \"\u002Fwebhooks\u002Fstripe\", method: \"POST\" },\n  async (req, res) => {\n    const sig = req.headers[\"stripe-signature\"];\n    \u002F\u002F Read raw body\n    const chunks: Buffer[] = [];\n    for await (const chunk of req) chunks.push(chunk);\n    const rawBody = Buffer.concat(chunks).toString(\"utf8\");\n\n    \u002F\u002F Verify signature, parse event...\n\n    res.writeHead(200, { \"Content-Type\": \"application\u002Fjson\" });\n    res.end(JSON.stringify({ received: true }));\n  }\n);\n",[165],{"type":47,"tag":69,"props":166,"children":167},{"__ignoreMap":89},[168,212,296,340,400,409,450,524,600,610,619,627,705,775,784],{"type":47,"tag":95,"props":169,"children":170},{"class":97,"line":98},[171,176,182,187,192,196,201,207],{"type":47,"tag":95,"props":172,"children":173},{"style":102},[174],{"type":53,"value":175},"export",{"type":47,"tag":95,"props":177,"children":179},{"style":178},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[180],{"type":53,"value":181}," const",{"type":47,"tag":95,"props":183,"children":184},{"style":114},[185],{"type":53,"value":186}," stripeWebhook ",{"type":47,"tag":95,"props":188,"children":189},{"style":108},[190],{"type":53,"value":191},"=",{"type":47,"tag":95,"props":193,"children":194},{"style":114},[195],{"type":53,"value":117},{"type":47,"tag":95,"props":197,"children":198},{"style":108},[199],{"type":53,"value":200},".",{"type":47,"tag":95,"props":202,"children":204},{"style":203},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[205],{"type":53,"value":206},"raw",{"type":47,"tag":95,"props":208,"children":209},{"style":114},[210],{"type":53,"value":211},"(\n",{"type":47,"tag":95,"props":213,"children":215},{"class":97,"line":214},2,[216,221,227,232,238,243,248,252,256,261,265,269,274,278,282,287,291],{"type":47,"tag":95,"props":217,"children":218},{"style":108},[219],{"type":53,"value":220},"  {",{"type":47,"tag":95,"props":222,"children":224},{"style":223},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[225],{"type":53,"value":226}," expose",{"type":47,"tag":95,"props":228,"children":229},{"style":108},[230],{"type":53,"value":231},":",{"type":47,"tag":95,"props":233,"children":235},{"style":234},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[236],{"type":53,"value":237}," true",{"type":47,"tag":95,"props":239,"children":240},{"style":108},[241],{"type":53,"value":242},",",{"type":47,"tag":95,"props":244,"children":245},{"style":223},[246],{"type":53,"value":247}," path",{"type":47,"tag":95,"props":249,"children":250},{"style":108},[251],{"type":53,"value":231},{"type":47,"tag":95,"props":253,"children":254},{"style":108},[255],{"type":53,"value":132},{"type":47,"tag":95,"props":257,"children":258},{"style":135},[259],{"type":53,"value":260},"\u002Fwebhooks\u002Fstripe",{"type":47,"tag":95,"props":262,"children":263},{"style":108},[264],{"type":53,"value":143},{"type":47,"tag":95,"props":266,"children":267},{"style":108},[268],{"type":53,"value":242},{"type":47,"tag":95,"props":270,"children":271},{"style":223},[272],{"type":53,"value":273}," method",{"type":47,"tag":95,"props":275,"children":276},{"style":108},[277],{"type":53,"value":231},{"type":47,"tag":95,"props":279,"children":280},{"style":108},[281],{"type":53,"value":132},{"type":47,"tag":95,"props":283,"children":284},{"style":135},[285],{"type":53,"value":286},"POST",{"type":47,"tag":95,"props":288,"children":289},{"style":108},[290],{"type":53,"value":143},{"type":47,"tag":95,"props":292,"children":293},{"style":108},[294],{"type":53,"value":295}," },\n",{"type":47,"tag":95,"props":297,"children":299},{"class":97,"line":298},3,[300,305,310,316,320,325,330,335],{"type":47,"tag":95,"props":301,"children":302},{"style":178},[303],{"type":53,"value":304},"  async",{"type":47,"tag":95,"props":306,"children":307},{"style":108},[308],{"type":53,"value":309}," (",{"type":47,"tag":95,"props":311,"children":313},{"style":312},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[314],{"type":53,"value":315},"req",{"type":47,"tag":95,"props":317,"children":318},{"style":108},[319],{"type":53,"value":242},{"type":47,"tag":95,"props":321,"children":322},{"style":312},[323],{"type":53,"value":324}," res",{"type":47,"tag":95,"props":326,"children":327},{"style":108},[328],{"type":53,"value":329},")",{"type":47,"tag":95,"props":331,"children":332},{"style":178},[333],{"type":53,"value":334}," =>",{"type":47,"tag":95,"props":336,"children":337},{"style":108},[338],{"type":53,"value":339}," {\n",{"type":47,"tag":95,"props":341,"children":343},{"class":97,"line":342},4,[344,349,354,359,364,368,373,378,382,387,391,396],{"type":47,"tag":95,"props":345,"children":346},{"style":178},[347],{"type":53,"value":348},"    const",{"type":47,"tag":95,"props":350,"children":351},{"style":114},[352],{"type":53,"value":353}," sig",{"type":47,"tag":95,"props":355,"children":356},{"style":108},[357],{"type":53,"value":358}," =",{"type":47,"tag":95,"props":360,"children":361},{"style":114},[362],{"type":53,"value":363}," req",{"type":47,"tag":95,"props":365,"children":366},{"style":108},[367],{"type":53,"value":200},{"type":47,"tag":95,"props":369,"children":370},{"style":114},[371],{"type":53,"value":372},"headers",{"type":47,"tag":95,"props":374,"children":375},{"style":223},[376],{"type":53,"value":377},"[",{"type":47,"tag":95,"props":379,"children":380},{"style":108},[381],{"type":53,"value":143},{"type":47,"tag":95,"props":383,"children":384},{"style":135},[385],{"type":53,"value":386},"stripe-signature",{"type":47,"tag":95,"props":388,"children":389},{"style":108},[390],{"type":53,"value":143},{"type":47,"tag":95,"props":392,"children":393},{"style":223},[394],{"type":53,"value":395},"]",{"type":47,"tag":95,"props":397,"children":398},{"style":108},[399],{"type":53,"value":148},{"type":47,"tag":95,"props":401,"children":402},{"class":97,"line":31},[403],{"type":47,"tag":95,"props":404,"children":406},{"style":405},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[407],{"type":53,"value":408},"    \u002F\u002F Read raw body\n",{"type":47,"tag":95,"props":410,"children":412},{"class":97,"line":411},6,[413,417,422,426,432,437,441,446],{"type":47,"tag":95,"props":414,"children":415},{"style":178},[416],{"type":53,"value":348},{"type":47,"tag":95,"props":418,"children":419},{"style":114},[420],{"type":53,"value":421}," chunks",{"type":47,"tag":95,"props":423,"children":424},{"style":108},[425],{"type":53,"value":231},{"type":47,"tag":95,"props":427,"children":429},{"style":428},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[430],{"type":53,"value":431}," Buffer",{"type":47,"tag":95,"props":433,"children":434},{"style":223},[435],{"type":53,"value":436},"[] ",{"type":47,"tag":95,"props":438,"children":439},{"style":108},[440],{"type":53,"value":191},{"type":47,"tag":95,"props":442,"children":443},{"style":223},[444],{"type":53,"value":445}," []",{"type":47,"tag":95,"props":447,"children":448},{"style":108},[449],{"type":53,"value":148},{"type":47,"tag":95,"props":451,"children":453},{"class":97,"line":452},7,[454,459,464,468,473,478,483,487,492,497,501,506,511,516,520],{"type":47,"tag":95,"props":455,"children":456},{"style":102},[457],{"type":53,"value":458},"    for",{"type":47,"tag":95,"props":460,"children":461},{"style":102},[462],{"type":53,"value":463}," await",{"type":47,"tag":95,"props":465,"children":466},{"style":223},[467],{"type":53,"value":309},{"type":47,"tag":95,"props":469,"children":470},{"style":178},[471],{"type":53,"value":472},"const",{"type":47,"tag":95,"props":474,"children":475},{"style":114},[476],{"type":53,"value":477}," chunk",{"type":47,"tag":95,"props":479,"children":480},{"style":108},[481],{"type":53,"value":482}," of",{"type":47,"tag":95,"props":484,"children":485},{"style":114},[486],{"type":53,"value":363},{"type":47,"tag":95,"props":488,"children":489},{"style":223},[490],{"type":53,"value":491},") ",{"type":47,"tag":95,"props":493,"children":494},{"style":114},[495],{"type":53,"value":496},"chunks",{"type":47,"tag":95,"props":498,"children":499},{"style":108},[500],{"type":53,"value":200},{"type":47,"tag":95,"props":502,"children":503},{"style":203},[504],{"type":53,"value":505},"push",{"type":47,"tag":95,"props":507,"children":508},{"style":223},[509],{"type":53,"value":510},"(",{"type":47,"tag":95,"props":512,"children":513},{"style":114},[514],{"type":53,"value":515},"chunk",{"type":47,"tag":95,"props":517,"children":518},{"style":223},[519],{"type":53,"value":329},{"type":47,"tag":95,"props":521,"children":522},{"style":108},[523],{"type":53,"value":148},{"type":47,"tag":95,"props":525,"children":527},{"class":97,"line":526},8,[528,532,537,541,545,549,554,558,562,566,570,575,579,583,588,592,596],{"type":47,"tag":95,"props":529,"children":530},{"style":178},[531],{"type":53,"value":348},{"type":47,"tag":95,"props":533,"children":534},{"style":114},[535],{"type":53,"value":536}," rawBody",{"type":47,"tag":95,"props":538,"children":539},{"style":108},[540],{"type":53,"value":358},{"type":47,"tag":95,"props":542,"children":543},{"style":114},[544],{"type":53,"value":431},{"type":47,"tag":95,"props":546,"children":547},{"style":108},[548],{"type":53,"value":200},{"type":47,"tag":95,"props":550,"children":551},{"style":203},[552],{"type":53,"value":553},"concat",{"type":47,"tag":95,"props":555,"children":556},{"style":223},[557],{"type":53,"value":510},{"type":47,"tag":95,"props":559,"children":560},{"style":114},[561],{"type":53,"value":496},{"type":47,"tag":95,"props":563,"children":564},{"style":223},[565],{"type":53,"value":329},{"type":47,"tag":95,"props":567,"children":568},{"style":108},[569],{"type":53,"value":200},{"type":47,"tag":95,"props":571,"children":572},{"style":203},[573],{"type":53,"value":574},"toString",{"type":47,"tag":95,"props":576,"children":577},{"style":223},[578],{"type":53,"value":510},{"type":47,"tag":95,"props":580,"children":581},{"style":108},[582],{"type":53,"value":143},{"type":47,"tag":95,"props":584,"children":585},{"style":135},[586],{"type":53,"value":587},"utf8",{"type":47,"tag":95,"props":589,"children":590},{"style":108},[591],{"type":53,"value":143},{"type":47,"tag":95,"props":593,"children":594},{"style":223},[595],{"type":53,"value":329},{"type":47,"tag":95,"props":597,"children":598},{"style":108},[599],{"type":53,"value":148},{"type":47,"tag":95,"props":601,"children":603},{"class":97,"line":602},9,[604],{"type":47,"tag":95,"props":605,"children":607},{"emptyLinePlaceholder":606},true,[608],{"type":53,"value":609},"\n",{"type":47,"tag":95,"props":611,"children":613},{"class":97,"line":612},10,[614],{"type":47,"tag":95,"props":615,"children":616},{"style":405},[617],{"type":53,"value":618},"    \u002F\u002F Verify signature, parse event...\n",{"type":47,"tag":95,"props":620,"children":622},{"class":97,"line":621},11,[623],{"type":47,"tag":95,"props":624,"children":625},{"emptyLinePlaceholder":606},[626],{"type":53,"value":609},{"type":47,"tag":95,"props":628,"children":630},{"class":97,"line":629},12,[631,636,640,645,649,655,659,663,667,672,676,680,684,689,693,697,701],{"type":47,"tag":95,"props":632,"children":633},{"style":114},[634],{"type":53,"value":635},"    res",{"type":47,"tag":95,"props":637,"children":638},{"style":108},[639],{"type":53,"value":200},{"type":47,"tag":95,"props":641,"children":642},{"style":203},[643],{"type":53,"value":644},"writeHead",{"type":47,"tag":95,"props":646,"children":647},{"style":223},[648],{"type":53,"value":510},{"type":47,"tag":95,"props":650,"children":652},{"style":651},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[653],{"type":53,"value":654},"200",{"type":47,"tag":95,"props":656,"children":657},{"style":108},[658],{"type":53,"value":242},{"type":47,"tag":95,"props":660,"children":661},{"style":108},[662],{"type":53,"value":111},{"type":47,"tag":95,"props":664,"children":665},{"style":108},[666],{"type":53,"value":132},{"type":47,"tag":95,"props":668,"children":669},{"style":223},[670],{"type":53,"value":671},"Content-Type",{"type":47,"tag":95,"props":673,"children":674},{"style":108},[675],{"type":53,"value":143},{"type":47,"tag":95,"props":677,"children":678},{"style":108},[679],{"type":53,"value":231},{"type":47,"tag":95,"props":681,"children":682},{"style":108},[683],{"type":53,"value":132},{"type":47,"tag":95,"props":685,"children":686},{"style":135},[687],{"type":53,"value":688},"application\u002Fjson",{"type":47,"tag":95,"props":690,"children":691},{"style":108},[692],{"type":53,"value":143},{"type":47,"tag":95,"props":694,"children":695},{"style":108},[696],{"type":53,"value":122},{"type":47,"tag":95,"props":698,"children":699},{"style":223},[700],{"type":53,"value":329},{"type":47,"tag":95,"props":702,"children":703},{"style":108},[704],{"type":53,"value":148},{"type":47,"tag":95,"props":706,"children":708},{"class":97,"line":707},13,[709,713,717,722,726,731,735,740,744,749,754,758,762,766,771],{"type":47,"tag":95,"props":710,"children":711},{"style":114},[712],{"type":53,"value":635},{"type":47,"tag":95,"props":714,"children":715},{"style":108},[716],{"type":53,"value":200},{"type":47,"tag":95,"props":718,"children":719},{"style":203},[720],{"type":53,"value":721},"end",{"type":47,"tag":95,"props":723,"children":724},{"style":223},[725],{"type":53,"value":510},{"type":47,"tag":95,"props":727,"children":728},{"style":114},[729],{"type":53,"value":730},"JSON",{"type":47,"tag":95,"props":732,"children":733},{"style":108},[734],{"type":53,"value":200},{"type":47,"tag":95,"props":736,"children":737},{"style":203},[738],{"type":53,"value":739},"stringify",{"type":47,"tag":95,"props":741,"children":742},{"style":223},[743],{"type":53,"value":510},{"type":47,"tag":95,"props":745,"children":746},{"style":108},[747],{"type":53,"value":748},"{",{"type":47,"tag":95,"props":750,"children":751},{"style":223},[752],{"type":53,"value":753}," received",{"type":47,"tag":95,"props":755,"children":756},{"style":108},[757],{"type":53,"value":231},{"type":47,"tag":95,"props":759,"children":760},{"style":234},[761],{"type":53,"value":237},{"type":47,"tag":95,"props":763,"children":764},{"style":108},[765],{"type":53,"value":122},{"type":47,"tag":95,"props":767,"children":768},{"style":223},[769],{"type":53,"value":770},"))",{"type":47,"tag":95,"props":772,"children":773},{"style":108},[774],{"type":53,"value":148},{"type":47,"tag":95,"props":776,"children":778},{"class":97,"line":777},14,[779],{"type":47,"tag":95,"props":780,"children":781},{"style":108},[782],{"type":53,"value":783},"  }\n",{"type":47,"tag":95,"props":785,"children":787},{"class":97,"line":786},15,[788,792],{"type":47,"tag":95,"props":789,"children":790},{"style":114},[791],{"type":53,"value":329},{"type":47,"tag":95,"props":793,"children":794},{"style":108},[795],{"type":53,"value":148},{"type":47,"tag":78,"props":797,"children":799},{"id":798},"_3-verify-the-signature",[800],{"type":53,"value":801},"3. Verify the signature",{"type":47,"tag":63,"props":803,"children":804},{},[805,807,813,815,821,823,829],{"type":53,"value":806},"Most providers sign webhooks. Read the secret with ",{"type":47,"tag":69,"props":808,"children":810},{"className":809},[],[811],{"type":53,"value":812},"secret(...)",{"type":53,"value":814}," from ",{"type":47,"tag":69,"props":816,"children":818},{"className":817},[],[819],{"type":53,"value":820},"encore.dev\u002Fconfig",{"type":53,"value":822}," (see the ",{"type":47,"tag":69,"props":824,"children":826},{"className":825},[],[827],{"type":53,"value":828},"encore-secret",{"type":53,"value":830}," skill) and verify before trusting the payload:",{"type":47,"tag":85,"props":832,"children":834},{"className":87,"code":833,"language":22,"meta":89,"style":89},"import { secret } from \"encore.dev\u002Fconfig\";\nconst stripeWebhookSecret = secret(\"StripeWebhookSecret\");\n\n\u002F\u002F inside handler:\nimport Stripe from \"stripe\";\nconst stripe = new Stripe(stripeApiKey());\nconst event = stripe.webhooks.constructEvent(rawBody, sig, stripeWebhookSecret());\n",[835],{"type":47,"tag":69,"props":836,"children":837},{"__ignoreMap":89},[838,878,923,930,938,972,1016],{"type":47,"tag":95,"props":839,"children":840},{"class":97,"line":98},[841,845,849,854,858,862,866,870,874],{"type":47,"tag":95,"props":842,"children":843},{"style":102},[844],{"type":53,"value":105},{"type":47,"tag":95,"props":846,"children":847},{"style":108},[848],{"type":53,"value":111},{"type":47,"tag":95,"props":850,"children":851},{"style":114},[852],{"type":53,"value":853}," secret",{"type":47,"tag":95,"props":855,"children":856},{"style":108},[857],{"type":53,"value":122},{"type":47,"tag":95,"props":859,"children":860},{"style":102},[861],{"type":53,"value":127},{"type":47,"tag":95,"props":863,"children":864},{"style":108},[865],{"type":53,"value":132},{"type":47,"tag":95,"props":867,"children":868},{"style":135},[869],{"type":53,"value":820},{"type":47,"tag":95,"props":871,"children":872},{"style":108},[873],{"type":53,"value":143},{"type":47,"tag":95,"props":875,"children":876},{"style":108},[877],{"type":53,"value":148},{"type":47,"tag":95,"props":879,"children":880},{"class":97,"line":214},[881,885,890,894,898,902,906,911,915,919],{"type":47,"tag":95,"props":882,"children":883},{"style":178},[884],{"type":53,"value":472},{"type":47,"tag":95,"props":886,"children":887},{"style":114},[888],{"type":53,"value":889}," stripeWebhookSecret ",{"type":47,"tag":95,"props":891,"children":892},{"style":108},[893],{"type":53,"value":191},{"type":47,"tag":95,"props":895,"children":896},{"style":203},[897],{"type":53,"value":853},{"type":47,"tag":95,"props":899,"children":900},{"style":114},[901],{"type":53,"value":510},{"type":47,"tag":95,"props":903,"children":904},{"style":108},[905],{"type":53,"value":143},{"type":47,"tag":95,"props":907,"children":908},{"style":135},[909],{"type":53,"value":910},"StripeWebhookSecret",{"type":47,"tag":95,"props":912,"children":913},{"style":108},[914],{"type":53,"value":143},{"type":47,"tag":95,"props":916,"children":917},{"style":114},[918],{"type":53,"value":329},{"type":47,"tag":95,"props":920,"children":921},{"style":108},[922],{"type":53,"value":148},{"type":47,"tag":95,"props":924,"children":925},{"class":97,"line":298},[926],{"type":47,"tag":95,"props":927,"children":928},{"emptyLinePlaceholder":606},[929],{"type":53,"value":609},{"type":47,"tag":95,"props":931,"children":932},{"class":97,"line":342},[933],{"type":47,"tag":95,"props":934,"children":935},{"style":405},[936],{"type":53,"value":937},"\u002F\u002F inside handler:\n",{"type":47,"tag":95,"props":939,"children":940},{"class":97,"line":31},[941,945,950,955,959,964,968],{"type":47,"tag":95,"props":942,"children":943},{"style":102},[944],{"type":53,"value":105},{"type":47,"tag":95,"props":946,"children":947},{"style":114},[948],{"type":53,"value":949}," Stripe ",{"type":47,"tag":95,"props":951,"children":952},{"style":102},[953],{"type":53,"value":954},"from",{"type":47,"tag":95,"props":956,"children":957},{"style":108},[958],{"type":53,"value":132},{"type":47,"tag":95,"props":960,"children":961},{"style":135},[962],{"type":53,"value":963},"stripe",{"type":47,"tag":95,"props":965,"children":966},{"style":108},[967],{"type":53,"value":143},{"type":47,"tag":95,"props":969,"children":970},{"style":108},[971],{"type":53,"value":148},{"type":47,"tag":95,"props":973,"children":974},{"class":97,"line":411},[975,979,984,988,993,998,1002,1007,1012],{"type":47,"tag":95,"props":976,"children":977},{"style":178},[978],{"type":53,"value":472},{"type":47,"tag":95,"props":980,"children":981},{"style":114},[982],{"type":53,"value":983}," stripe ",{"type":47,"tag":95,"props":985,"children":986},{"style":108},[987],{"type":53,"value":191},{"type":47,"tag":95,"props":989,"children":990},{"style":108},[991],{"type":53,"value":992}," new",{"type":47,"tag":95,"props":994,"children":995},{"style":203},[996],{"type":53,"value":997}," Stripe",{"type":47,"tag":95,"props":999,"children":1000},{"style":114},[1001],{"type":53,"value":510},{"type":47,"tag":95,"props":1003,"children":1004},{"style":203},[1005],{"type":53,"value":1006},"stripeApiKey",{"type":47,"tag":95,"props":1008,"children":1009},{"style":114},[1010],{"type":53,"value":1011},"())",{"type":47,"tag":95,"props":1013,"children":1014},{"style":108},[1015],{"type":53,"value":148},{"type":47,"tag":95,"props":1017,"children":1018},{"class":97,"line":452},[1019,1023,1028,1032,1037,1041,1045,1049,1054,1059,1063,1067,1071,1076,1080],{"type":47,"tag":95,"props":1020,"children":1021},{"style":178},[1022],{"type":53,"value":472},{"type":47,"tag":95,"props":1024,"children":1025},{"style":114},[1026],{"type":53,"value":1027}," event ",{"type":47,"tag":95,"props":1029,"children":1030},{"style":108},[1031],{"type":53,"value":191},{"type":47,"tag":95,"props":1033,"children":1034},{"style":114},[1035],{"type":53,"value":1036}," stripe",{"type":47,"tag":95,"props":1038,"children":1039},{"style":108},[1040],{"type":53,"value":200},{"type":47,"tag":95,"props":1042,"children":1043},{"style":114},[1044],{"type":53,"value":26},{"type":47,"tag":95,"props":1046,"children":1047},{"style":108},[1048],{"type":53,"value":200},{"type":47,"tag":95,"props":1050,"children":1051},{"style":203},[1052],{"type":53,"value":1053},"constructEvent",{"type":47,"tag":95,"props":1055,"children":1056},{"style":114},[1057],{"type":53,"value":1058},"(rawBody",{"type":47,"tag":95,"props":1060,"children":1061},{"style":108},[1062],{"type":53,"value":242},{"type":47,"tag":95,"props":1064,"children":1065},{"style":114},[1066],{"type":53,"value":353},{"type":47,"tag":95,"props":1068,"children":1069},{"style":108},[1070],{"type":53,"value":242},{"type":47,"tag":95,"props":1072,"children":1073},{"style":203},[1074],{"type":53,"value":1075}," stripeWebhookSecret",{"type":47,"tag":95,"props":1077,"children":1078},{"style":114},[1079],{"type":53,"value":1011},{"type":47,"tag":95,"props":1081,"children":1082},{"style":108},[1083],{"type":53,"value":148},{"type":47,"tag":63,"props":1085,"children":1086},{},[1087,1089,1095],{"type":53,"value":1088},"For GitHub, verify the HMAC-SHA256 in the ",{"type":47,"tag":69,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":53,"value":1094},"X-Hub-Signature-256",{"type":53,"value":1096}," header against the raw body using your webhook secret.",{"type":47,"tag":56,"props":1098,"children":1100},{"id":1099},"common-providers",[1101],{"type":53,"value":1102},"Common providers",{"type":47,"tag":1104,"props":1105,"children":1106},"table",{},[1107,1131],{"type":47,"tag":1108,"props":1109,"children":1110},"thead",{},[1111],{"type":47,"tag":1112,"props":1113,"children":1114},"tr",{},[1115,1121,1126],{"type":47,"tag":1116,"props":1117,"children":1118},"th",{},[1119],{"type":53,"value":1120},"Provider",{"type":47,"tag":1116,"props":1122,"children":1123},{},[1124],{"type":53,"value":1125},"Signature header",{"type":47,"tag":1116,"props":1127,"children":1128},{},[1129],{"type":53,"value":1130},"Verification",{"type":47,"tag":1132,"props":1133,"children":1134},"tbody",{},[1135,1162,1183,1211,1233],{"type":47,"tag":1112,"props":1136,"children":1137},{},[1138,1144,1153],{"type":47,"tag":1139,"props":1140,"children":1141},"td",{},[1142],{"type":53,"value":1143},"Stripe",{"type":47,"tag":1139,"props":1145,"children":1146},{},[1147],{"type":47,"tag":69,"props":1148,"children":1150},{"className":1149},[],[1151],{"type":53,"value":1152},"Stripe-Signature",{"type":47,"tag":1139,"props":1154,"children":1155},{},[1156],{"type":47,"tag":69,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":53,"value":1161},"stripe.webhooks.constructEvent(rawBody, sig, secret)",{"type":47,"tag":1112,"props":1163,"children":1164},{},[1165,1170,1178],{"type":47,"tag":1139,"props":1166,"children":1167},{},[1168],{"type":53,"value":1169},"GitHub",{"type":47,"tag":1139,"props":1171,"children":1172},{},[1173],{"type":47,"tag":69,"props":1174,"children":1176},{"className":1175},[],[1177],{"type":53,"value":1094},{"type":47,"tag":1139,"props":1179,"children":1180},{},[1181],{"type":53,"value":1182},"HMAC-SHA256 over the raw body",{"type":47,"tag":1112,"props":1184,"children":1185},{},[1186,1191,1200],{"type":47,"tag":1139,"props":1187,"children":1188},{},[1189],{"type":53,"value":1190},"Slack",{"type":47,"tag":1139,"props":1192,"children":1193},{},[1194],{"type":47,"tag":69,"props":1195,"children":1197},{"className":1196},[],[1198],{"type":53,"value":1199},"X-Slack-Signature",{"type":47,"tag":1139,"props":1201,"children":1202},{},[1203,1205],{"type":53,"value":1204},"HMAC-SHA256 over ",{"type":47,"tag":69,"props":1206,"children":1208},{"className":1207},[],[1209],{"type":53,"value":1210},"v0:{timestamp}:{rawBody}",{"type":47,"tag":1112,"props":1212,"children":1213},{},[1214,1219,1228],{"type":47,"tag":1139,"props":1215,"children":1216},{},[1217],{"type":53,"value":1218},"Shopify",{"type":47,"tag":1139,"props":1220,"children":1221},{},[1222],{"type":47,"tag":69,"props":1223,"children":1225},{"className":1224},[],[1226],{"type":53,"value":1227},"X-Shopify-Hmac-Sha256",{"type":47,"tag":1139,"props":1229,"children":1230},{},[1231],{"type":53,"value":1232},"HMAC-SHA256 (base64) over the raw body",{"type":47,"tag":1112,"props":1234,"children":1235},{},[1236,1241,1250],{"type":47,"tag":1139,"props":1237,"children":1238},{},[1239],{"type":53,"value":1240},"Twilio",{"type":47,"tag":1139,"props":1242,"children":1243},{},[1244],{"type":47,"tag":69,"props":1245,"children":1247},{"className":1246},[],[1248],{"type":53,"value":1249},"X-Twilio-Signature",{"type":47,"tag":1139,"props":1251,"children":1252},{},[1253],{"type":53,"value":1254},"HMAC-SHA1 over URL + sorted form fields",{"type":47,"tag":56,"props":1256,"children":1258},{"id":1257},"always-respond-quickly",[1259],{"type":53,"value":1260},"Always respond quickly",{"type":47,"tag":63,"props":1262,"children":1263},{},[1264,1266,1272],{"type":53,"value":1265},"Webhook senders retry on non-2xx or slow responses. Acknowledge with a 2xx as soon as the payload is verified, then enqueue the actual work via Pub\u002FSub (see ",{"type":47,"tag":69,"props":1267,"children":1269},{"className":1268},[],[1270],{"type":53,"value":1271},"encore-pubsub",{"type":53,"value":1273},") instead of doing it in the request handler.",{"type":47,"tag":85,"props":1275,"children":1277},{"className":87,"code":1276,"language":22,"meta":89,"style":89},"import { Topic } from \"encore.dev\u002Fpubsub\";\n\ninterface StripeEvent { id: string; type: string; data: unknown; }\nconst stripeEvents = new Topic\u003CStripeEvent>(\"stripe-events\", {\n  deliveryGuarantee: \"at-least-once\",\n});\n\n\u002F\u002F inside the raw handler, after verification:\nawait stripeEvents.publish({ id: event.id, type: event.type, data: event.data });\nres.writeHead(200); res.end();\n",[1278],{"type":47,"tag":69,"props":1279,"children":1280},{"__ignoreMap":89},[1281,1322,1329,1405,1469,1499,1515,1522,1530,1644],{"type":47,"tag":95,"props":1282,"children":1283},{"class":97,"line":98},[1284,1288,1292,1297,1301,1305,1309,1314,1318],{"type":47,"tag":95,"props":1285,"children":1286},{"style":102},[1287],{"type":53,"value":105},{"type":47,"tag":95,"props":1289,"children":1290},{"style":108},[1291],{"type":53,"value":111},{"type":47,"tag":95,"props":1293,"children":1294},{"style":114},[1295],{"type":53,"value":1296}," Topic",{"type":47,"tag":95,"props":1298,"children":1299},{"style":108},[1300],{"type":53,"value":122},{"type":47,"tag":95,"props":1302,"children":1303},{"style":102},[1304],{"type":53,"value":127},{"type":47,"tag":95,"props":1306,"children":1307},{"style":108},[1308],{"type":53,"value":132},{"type":47,"tag":95,"props":1310,"children":1311},{"style":135},[1312],{"type":53,"value":1313},"encore.dev\u002Fpubsub",{"type":47,"tag":95,"props":1315,"children":1316},{"style":108},[1317],{"type":53,"value":143},{"type":47,"tag":95,"props":1319,"children":1320},{"style":108},[1321],{"type":53,"value":148},{"type":47,"tag":95,"props":1323,"children":1324},{"class":97,"line":214},[1325],{"type":47,"tag":95,"props":1326,"children":1327},{"emptyLinePlaceholder":606},[1328],{"type":53,"value":609},{"type":47,"tag":95,"props":1330,"children":1331},{"class":97,"line":298},[1332,1337,1342,1346,1351,1355,1360,1365,1370,1374,1378,1382,1387,1391,1396,1400],{"type":47,"tag":95,"props":1333,"children":1334},{"style":178},[1335],{"type":53,"value":1336},"interface",{"type":47,"tag":95,"props":1338,"children":1339},{"style":428},[1340],{"type":53,"value":1341}," StripeEvent",{"type":47,"tag":95,"props":1343,"children":1344},{"style":108},[1345],{"type":53,"value":111},{"type":47,"tag":95,"props":1347,"children":1348},{"style":223},[1349],{"type":53,"value":1350}," id",{"type":47,"tag":95,"props":1352,"children":1353},{"style":108},[1354],{"type":53,"value":231},{"type":47,"tag":95,"props":1356,"children":1357},{"style":428},[1358],{"type":53,"value":1359}," string",{"type":47,"tag":95,"props":1361,"children":1362},{"style":108},[1363],{"type":53,"value":1364},";",{"type":47,"tag":95,"props":1366,"children":1367},{"style":223},[1368],{"type":53,"value":1369}," type",{"type":47,"tag":95,"props":1371,"children":1372},{"style":108},[1373],{"type":53,"value":231},{"type":47,"tag":95,"props":1375,"children":1376},{"style":428},[1377],{"type":53,"value":1359},{"type":47,"tag":95,"props":1379,"children":1380},{"style":108},[1381],{"type":53,"value":1364},{"type":47,"tag":95,"props":1383,"children":1384},{"style":223},[1385],{"type":53,"value":1386}," data",{"type":47,"tag":95,"props":1388,"children":1389},{"style":108},[1390],{"type":53,"value":231},{"type":47,"tag":95,"props":1392,"children":1393},{"style":428},[1394],{"type":53,"value":1395}," unknown",{"type":47,"tag":95,"props":1397,"children":1398},{"style":108},[1399],{"type":53,"value":1364},{"type":47,"tag":95,"props":1401,"children":1402},{"style":108},[1403],{"type":53,"value":1404}," }\n",{"type":47,"tag":95,"props":1406,"children":1407},{"class":97,"line":342},[1408,1412,1417,1421,1425,1429,1434,1439,1444,1448,1452,1457,1461,1465],{"type":47,"tag":95,"props":1409,"children":1410},{"style":178},[1411],{"type":53,"value":472},{"type":47,"tag":95,"props":1413,"children":1414},{"style":114},[1415],{"type":53,"value":1416}," stripeEvents ",{"type":47,"tag":95,"props":1418,"children":1419},{"style":108},[1420],{"type":53,"value":191},{"type":47,"tag":95,"props":1422,"children":1423},{"style":108},[1424],{"type":53,"value":992},{"type":47,"tag":95,"props":1426,"children":1427},{"style":203},[1428],{"type":53,"value":1296},{"type":47,"tag":95,"props":1430,"children":1431},{"style":108},[1432],{"type":53,"value":1433},"\u003C",{"type":47,"tag":95,"props":1435,"children":1436},{"style":428},[1437],{"type":53,"value":1438},"StripeEvent",{"type":47,"tag":95,"props":1440,"children":1441},{"style":108},[1442],{"type":53,"value":1443},">",{"type":47,"tag":95,"props":1445,"children":1446},{"style":114},[1447],{"type":53,"value":510},{"type":47,"tag":95,"props":1449,"children":1450},{"style":108},[1451],{"type":53,"value":143},{"type":47,"tag":95,"props":1453,"children":1454},{"style":135},[1455],{"type":53,"value":1456},"stripe-events",{"type":47,"tag":95,"props":1458,"children":1459},{"style":108},[1460],{"type":53,"value":143},{"type":47,"tag":95,"props":1462,"children":1463},{"style":108},[1464],{"type":53,"value":242},{"type":47,"tag":95,"props":1466,"children":1467},{"style":108},[1468],{"type":53,"value":339},{"type":47,"tag":95,"props":1470,"children":1471},{"class":97,"line":31},[1472,1477,1481,1485,1490,1494],{"type":47,"tag":95,"props":1473,"children":1474},{"style":223},[1475],{"type":53,"value":1476},"  deliveryGuarantee",{"type":47,"tag":95,"props":1478,"children":1479},{"style":108},[1480],{"type":53,"value":231},{"type":47,"tag":95,"props":1482,"children":1483},{"style":108},[1484],{"type":53,"value":132},{"type":47,"tag":95,"props":1486,"children":1487},{"style":135},[1488],{"type":53,"value":1489},"at-least-once",{"type":47,"tag":95,"props":1491,"children":1492},{"style":108},[1493],{"type":53,"value":143},{"type":47,"tag":95,"props":1495,"children":1496},{"style":108},[1497],{"type":53,"value":1498},",\n",{"type":47,"tag":95,"props":1500,"children":1501},{"class":97,"line":411},[1502,1507,1511],{"type":47,"tag":95,"props":1503,"children":1504},{"style":108},[1505],{"type":53,"value":1506},"}",{"type":47,"tag":95,"props":1508,"children":1509},{"style":114},[1510],{"type":53,"value":329},{"type":47,"tag":95,"props":1512,"children":1513},{"style":108},[1514],{"type":53,"value":148},{"type":47,"tag":95,"props":1516,"children":1517},{"class":97,"line":452},[1518],{"type":47,"tag":95,"props":1519,"children":1520},{"emptyLinePlaceholder":606},[1521],{"type":53,"value":609},{"type":47,"tag":95,"props":1523,"children":1524},{"class":97,"line":526},[1525],{"type":47,"tag":95,"props":1526,"children":1527},{"style":405},[1528],{"type":53,"value":1529},"\u002F\u002F inside the raw handler, after verification:\n",{"type":47,"tag":95,"props":1531,"children":1532},{"class":97,"line":602},[1533,1538,1543,1547,1552,1556,1560,1564,1568,1573,1577,1582,1586,1590,1594,1598,1602,1607,1611,1615,1619,1623,1627,1632,1636,1640],{"type":47,"tag":95,"props":1534,"children":1535},{"style":102},[1536],{"type":53,"value":1537},"await",{"type":47,"tag":95,"props":1539,"children":1540},{"style":114},[1541],{"type":53,"value":1542}," stripeEvents",{"type":47,"tag":95,"props":1544,"children":1545},{"style":108},[1546],{"type":53,"value":200},{"type":47,"tag":95,"props":1548,"children":1549},{"style":203},[1550],{"type":53,"value":1551},"publish",{"type":47,"tag":95,"props":1553,"children":1554},{"style":114},[1555],{"type":53,"value":510},{"type":47,"tag":95,"props":1557,"children":1558},{"style":108},[1559],{"type":53,"value":748},{"type":47,"tag":95,"props":1561,"children":1562},{"style":223},[1563],{"type":53,"value":1350},{"type":47,"tag":95,"props":1565,"children":1566},{"style":108},[1567],{"type":53,"value":231},{"type":47,"tag":95,"props":1569,"children":1570},{"style":114},[1571],{"type":53,"value":1572}," event",{"type":47,"tag":95,"props":1574,"children":1575},{"style":108},[1576],{"type":53,"value":200},{"type":47,"tag":95,"props":1578,"children":1579},{"style":114},[1580],{"type":53,"value":1581},"id",{"type":47,"tag":95,"props":1583,"children":1584},{"style":108},[1585],{"type":53,"value":242},{"type":47,"tag":95,"props":1587,"children":1588},{"style":223},[1589],{"type":53,"value":1369},{"type":47,"tag":95,"props":1591,"children":1592},{"style":108},[1593],{"type":53,"value":231},{"type":47,"tag":95,"props":1595,"children":1596},{"style":114},[1597],{"type":53,"value":1572},{"type":47,"tag":95,"props":1599,"children":1600},{"style":108},[1601],{"type":53,"value":200},{"type":47,"tag":95,"props":1603,"children":1604},{"style":114},[1605],{"type":53,"value":1606},"type",{"type":47,"tag":95,"props":1608,"children":1609},{"style":108},[1610],{"type":53,"value":242},{"type":47,"tag":95,"props":1612,"children":1613},{"style":223},[1614],{"type":53,"value":1386},{"type":47,"tag":95,"props":1616,"children":1617},{"style":108},[1618],{"type":53,"value":231},{"type":47,"tag":95,"props":1620,"children":1621},{"style":114},[1622],{"type":53,"value":1572},{"type":47,"tag":95,"props":1624,"children":1625},{"style":108},[1626],{"type":53,"value":200},{"type":47,"tag":95,"props":1628,"children":1629},{"style":114},[1630],{"type":53,"value":1631},"data ",{"type":47,"tag":95,"props":1633,"children":1634},{"style":108},[1635],{"type":53,"value":1506},{"type":47,"tag":95,"props":1637,"children":1638},{"style":114},[1639],{"type":53,"value":329},{"type":47,"tag":95,"props":1641,"children":1642},{"style":108},[1643],{"type":53,"value":148},{"type":47,"tag":95,"props":1645,"children":1646},{"class":97,"line":612},[1647,1652,1656,1660,1664,1668,1672,1676,1680,1684,1688,1693],{"type":47,"tag":95,"props":1648,"children":1649},{"style":114},[1650],{"type":53,"value":1651},"res",{"type":47,"tag":95,"props":1653,"children":1654},{"style":108},[1655],{"type":53,"value":200},{"type":47,"tag":95,"props":1657,"children":1658},{"style":203},[1659],{"type":53,"value":644},{"type":47,"tag":95,"props":1661,"children":1662},{"style":114},[1663],{"type":53,"value":510},{"type":47,"tag":95,"props":1665,"children":1666},{"style":651},[1667],{"type":53,"value":654},{"type":47,"tag":95,"props":1669,"children":1670},{"style":114},[1671],{"type":53,"value":329},{"type":47,"tag":95,"props":1673,"children":1674},{"style":108},[1675],{"type":53,"value":1364},{"type":47,"tag":95,"props":1677,"children":1678},{"style":114},[1679],{"type":53,"value":324},{"type":47,"tag":95,"props":1681,"children":1682},{"style":108},[1683],{"type":53,"value":200},{"type":47,"tag":95,"props":1685,"children":1686},{"style":203},[1687],{"type":53,"value":721},{"type":47,"tag":95,"props":1689,"children":1690},{"style":114},[1691],{"type":53,"value":1692},"()",{"type":47,"tag":95,"props":1694,"children":1695},{"style":108},[1696],{"type":53,"value":148},{"type":47,"tag":56,"props":1698,"children":1700},{"id":1699},"guidelines",[1701],{"type":53,"value":1702},"Guidelines",{"type":47,"tag":1704,"props":1705,"children":1706},"ul",{},[1707,1727,1732,1737,1749],{"type":47,"tag":1708,"props":1709,"children":1710},"li",{},[1711,1712,1717,1719,1725],{"type":53,"value":67},{"type":47,"tag":69,"props":1713,"children":1715},{"className":1714},[],[1716],{"type":53,"value":160},{"type":53,"value":1718}," ",{"type":47,"tag":1720,"props":1721,"children":1722},"em",{},[1723],{"type":53,"value":1724},"only",{"type":53,"value":1726}," for webhooks and other low-level HTTP integrations.",{"type":47,"tag":1708,"props":1728,"children":1729},{},[1730],{"type":53,"value":1731},"Always verify the provider's signature before trusting the payload.",{"type":47,"tag":1708,"props":1733,"children":1734},{},[1735],{"type":53,"value":1736},"Always respond 2xx fast — push slow work onto Pub\u002FSub.",{"type":47,"tag":1708,"props":1738,"children":1739},{},[1740,1742,1747],{"type":53,"value":1741},"Store the signing secret with ",{"type":47,"tag":69,"props":1743,"children":1745},{"className":1744},[],[1746],{"type":53,"value":812},{"type":53,"value":1748},"; never inline it.",{"type":47,"tag":1708,"props":1750,"children":1751},{},[1752,1754,1760,1762,1768],{"type":53,"value":1753},"For typed JSON endpoints in your own service, use plain ",{"type":47,"tag":69,"props":1755,"children":1757},{"className":1756},[],[1758],{"type":53,"value":1759},"api(...)",{"type":53,"value":1761}," from the ",{"type":47,"tag":69,"props":1763,"children":1765},{"className":1764},[],[1766],{"type":53,"value":1767},"encore-api",{"type":53,"value":1769}," skill.",{"type":47,"tag":1771,"props":1772,"children":1773},"style",{},[1774],{"type":53,"value":1775},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1777,"total":1876},[1778,1789,1801,1817,1833,1845,1861],{"slug":1767,"name":1767,"fn":1779,"description":1780,"org":1781,"tags":1782,"stars":27,"repoUrl":28,"updatedAt":1788},"build type-safe APIs with Encore","Define typed API endpoints in Encore.ts using `api(...)` from `encore.dev\u002Fapi`. Covers typed request\u002Fresponse interfaces, path\u002Fquery\u002Fheader\u002Fcookie params, request validation, and `APIError`. For raw endpoints (`api.raw()`) and inbound webhooks, use `encore-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1783,1786,1787],{"name":1784,"slug":1785,"type":16},"API Development","api-development",{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},"2026-04-06T18:09:46.044101",{"slug":1790,"name":1790,"fn":1791,"description":1792,"org":1793,"tags":1794,"stars":27,"repoUrl":28,"updatedAt":1800},"encore-auth","implement Encore.ts authentication","Protect Encore.ts endpoints with authentication and authorize callers. Covers `authHandler`, `Gateway`, `getAuthData`, and `auth: true`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1795,1798,1799],{"name":1796,"slug":1797,"type":16},"Auth","auth",{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},"2026-04-06T18:09:47.336322",{"slug":1802,"name":1802,"fn":1803,"description":1804,"org":1805,"tags":1806,"stars":27,"repoUrl":28,"updatedAt":1816},"encore-bucket","store files in Encore.ts buckets","Store unstructured files in Encore.ts using `Bucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1807,1808,1809,1812,1815],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1810,"slug":1811,"type":16},"File Storage","file-storage",{"name":1813,"slug":1814,"type":16},"File Uploads","file-uploads",{"name":21,"slug":22,"type":16},"2026-05-16T05:59:52.813772",{"slug":1818,"name":1818,"fn":1819,"description":1820,"org":1821,"tags":1822,"stars":27,"repoUrl":28,"updatedAt":1832},"encore-cache","cache data in Redis with Encore.ts","Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev\u002Fstorage\u002Fcache`. Type-safe key\u002Fvalue access with TTLs, atomic increments, and per-keyspace data shapes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1823,1824,1827,1828,1831],{"name":14,"slug":15,"type":16},{"name":1825,"slug":1826,"type":16},"Caching","caching",{"name":9,"slug":8,"type":16},{"name":1829,"slug":1830,"type":16},"Redis","redis",{"name":21,"slug":22,"type":16},"2026-05-16T05:59:56.808328",{"slug":1834,"name":1834,"fn":1835,"description":1836,"org":1837,"tags":1838,"stars":27,"repoUrl":28,"updatedAt":1844},"encore-code-review","review Encore.ts code","Review existing Encore.ts code for best practices and common anti-patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1839,1842,1843],{"name":1840,"slug":1841,"type":16},"Code Review","code-review",{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},"2026-04-06T18:10:01.123999",{"slug":1846,"name":1846,"fn":1847,"description":1848,"org":1849,"tags":1850,"stars":27,"repoUrl":28,"updatedAt":1860},"encore-cron","schedule recurring jobs in Encore.ts","Schedule periodic \u002F recurring work in Encore.ts using `CronJob` from `encore.dev\u002Fcron`. Covers `every: \"1h\"` interval syntax and `schedule: \"0 9 * * 1\"` cron expressions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1851,1854,1855,1856,1859],{"name":1852,"slug":1853,"type":16},"Automation","automation",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1857,"slug":1858,"type":16},"Scheduling","scheduling",{"name":21,"slug":22,"type":16},"2026-05-16T05:59:54.146651",{"slug":1862,"name":1862,"fn":1863,"description":1864,"org":1865,"tags":1866,"stars":27,"repoUrl":28,"updatedAt":1875},"encore-database","build Encore databases","Work with PostgreSQL in Encore.ts using `SQLDatabase` from `encore.dev\u002Fstorage\u002Fsqldb` — schema migrations and SQL queries.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1867,1870,1871,1874],{"name":1868,"slug":1869,"type":16},"Database","database",{"name":9,"slug":8,"type":16},{"name":1872,"slug":1873,"type":16},"ORM","orm",{"name":21,"slug":22,"type":16},"2026-04-06T18:09:54.823017",28,{"items":1878,"total":1876},[1879,1885,1891,1899,1907,1913,1921,1928,1945,1962,1974,1985],{"slug":1767,"name":1767,"fn":1779,"description":1780,"org":1880,"tags":1881,"stars":27,"repoUrl":28,"updatedAt":1788},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1882,1883,1884],{"name":1784,"slug":1785,"type":16},{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},{"slug":1790,"name":1790,"fn":1791,"description":1792,"org":1886,"tags":1887,"stars":27,"repoUrl":28,"updatedAt":1800},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1888,1889,1890],{"name":1796,"slug":1797,"type":16},{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},{"slug":1802,"name":1802,"fn":1803,"description":1804,"org":1892,"tags":1893,"stars":27,"repoUrl":28,"updatedAt":1816},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1894,1895,1896,1897,1898],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1810,"slug":1811,"type":16},{"name":1813,"slug":1814,"type":16},{"name":21,"slug":22,"type":16},{"slug":1818,"name":1818,"fn":1819,"description":1820,"org":1900,"tags":1901,"stars":27,"repoUrl":28,"updatedAt":1832},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1902,1903,1904,1905,1906],{"name":14,"slug":15,"type":16},{"name":1825,"slug":1826,"type":16},{"name":9,"slug":8,"type":16},{"name":1829,"slug":1830,"type":16},{"name":21,"slug":22,"type":16},{"slug":1834,"name":1834,"fn":1835,"description":1836,"org":1908,"tags":1909,"stars":27,"repoUrl":28,"updatedAt":1844},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1910,1911,1912],{"name":1840,"slug":1841,"type":16},{"name":9,"slug":8,"type":16},{"name":21,"slug":22,"type":16},{"slug":1846,"name":1846,"fn":1847,"description":1848,"org":1914,"tags":1915,"stars":27,"repoUrl":28,"updatedAt":1860},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1916,1917,1918,1919,1920],{"name":1852,"slug":1853,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1857,"slug":1858,"type":16},{"name":21,"slug":22,"type":16},{"slug":1862,"name":1862,"fn":1863,"description":1864,"org":1922,"tags":1923,"stars":27,"repoUrl":28,"updatedAt":1875},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1924,1925,1926,1927],{"name":1868,"slug":1869,"type":16},{"name":9,"slug":8,"type":16},{"name":1872,"slug":1873,"type":16},{"name":21,"slug":22,"type":16},{"slug":1929,"name":1929,"fn":1930,"description":1931,"org":1932,"tags":1933,"stars":27,"repoUrl":28,"updatedAt":1944},"encore-frontend","connect frontend to Encore backend","Connect a frontend application (React, Next.js, Vue, Svelte, etc.) to an Encore.ts backend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1934,1935,1938,1941],{"name":9,"slug":8,"type":16},{"name":1936,"slug":1937,"type":16},"Frontend","frontend",{"name":1939,"slug":1940,"type":16},"Next.js","next-js",{"name":1942,"slug":1943,"type":16},"React","react","2026-04-06T18:09:56.091006",{"slug":1946,"name":1946,"fn":1947,"description":1948,"org":1949,"tags":1950,"stars":27,"repoUrl":28,"updatedAt":1961},"encore-getting-started","build and run applications with Encore.ts","Bootstrap a brand-new Encore.ts project from zero. Only for first-time CLI install and `encore app create` — not for architecture or feature questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1951,1952,1953,1954,1957,1958],{"name":1784,"slug":1785,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1955,"slug":1956,"type":16},"Local Development","local-development",{"name":21,"slug":22,"type":16},{"name":1959,"slug":1960,"type":16},"Web Development","web-development","2026-04-06T18:10:04.885446",{"slug":1963,"name":1963,"fn":1964,"description":1965,"org":1966,"tags":1967,"stars":27,"repoUrl":28,"updatedAt":1973},"encore-go-api","build APIs with Encore Go","Define typed API endpoints in Encore Go using `\u002F\u002Fencore:api` annotations. Covers typed request\u002Fresponse structs, path\u002Fquery\u002Fheader\u002Fcookie params, and error returns. For raw endpoints (`\u002F\u002Fencore:api raw`) and inbound webhooks, use `encore-go-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1968,1969,1970],{"name":1784,"slug":1785,"type":16},{"name":9,"slug":8,"type":16},{"name":1971,"slug":1972,"type":16},"Go","go","2026-04-06T18:09:48.578781",{"slug":1975,"name":1975,"fn":1976,"description":1977,"org":1978,"tags":1979,"stars":27,"repoUrl":28,"updatedAt":1984},"encore-go-auth","implement authentication with Encore Go","Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `\u002F\u002Fencore:api auth`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1980,1981,1982,1983],{"name":1796,"slug":1797,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1971,"slug":1972,"type":16},"2026-04-06T18:09:51.065102",{"slug":1986,"name":1986,"fn":1987,"description":1988,"org":1989,"tags":1990,"stars":27,"repoUrl":28,"updatedAt":1998},"encore-go-bucket","store files in Encore Go buckets","Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1991,1992,1993,1994,1995],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":1810,"slug":1811,"type":16},{"name":1971,"slug":1972,"type":16},{"name":1996,"slug":1997,"type":16},"Storage","storage","2026-05-16T06:00:03.633918"]