nvoke

Use case

Webhook handlers, without the server.

Every service you integrate with — Stripe, GitHub, Shopify, Slack, Linear, Zapier — wants an HTTPS URL to POST to. nvoke gives you that URL in seconds, with logs, retries, and a real editor.

import crypto from "node:crypto";

export default async function (req) {
  const sig = req.headers["x-hub-signature-256"];
  const expected =
    "sha256=" +
    crypto
      .createHmac("sha256", process.env.WEBHOOK_SECRET)
      .update(req.rawBody)
      .digest("hex");

  if (sig !== expected) return new Response("bad sig", { status: 401 });

  const event = req.body;
  if (event.action === "opened") {
    await notifySlack(`New issue: ${event.issue.title}`);
  }
  return { ok: true };
}
A GitHub webhook handler with signature verification.

Why webhooks are the best case for nvoke

A webhook handler is the platonic ideal of a nvoke function. The shape of the work is receive a POST, do something, return quickly. There is no long-running state, no user session to track, no view to render. You want the code deployed somewhere with a URL you can paste into a webhook field, and you want to see logs when it fires.

The alternative is usually running a small Express app on a VPS, a Next.js route on Vercel, or a Lambda behind API Gateway. All of those work. All of them also make you carry a lot of infrastructure for what is usually fewer than fifty lines of code.

Signature verification

Every serious webhook sender signs the request. Stripe uses HMAC-SHA256 over the body; GitHub does the same with a different header; Shopify uses base64 HMAC. The pattern is the same: read the signature header, compute an HMAC over the raw body with your shared secret, compare with crypto.timingSafeEqual.

nvoke exposes req.rawBody as a Buffer so you can verify without worrying about JSON round-trip mutations. The parsed body is on req.body as usual.

Responding to retries

Webhook senders retry on non-2xx responses, usually with exponential backoff. That means two things for your handler. First: return fast. If you need to do heavy work, return 200 immediately and do the work out of band (a scheduled nvoke function polling a queue is a fine pattern). Second: be idempotent. The same event may arrive twice, and your function should not double-charge a customer or double-send a notification.

Ship a webhook handler today.

Create a function, copy the URL, paste it into the sender's dashboard. Done.