Hono 4.13.10 split adapters: update a Sume webhook receiver

Hono 4.13.10 moved adapters to @hono/bun, @hono/deno and @hono/cloudflare-workers. The Sume verifyWebhook call needs no change; only the entrypoint imports do.

4 min readSume
All posts

If you run a Sume webhook receiver on Hono, the 4.13.10 adapter split changes your imports and nothing in the verification code. The Hono release notes dated 2026-09-28 say the adapters now ship as separate packages, and that hono/<adapter> imports are deprecated and removed in v5. The Sume verifyWebhook helper uses WebCrypto, so the same handler runs on Bun, Deno and Workers.

What the Hono releases say

Version 4.13.10 (2026-09-28) lists the new packages. hono/cloudflare-pages is deprecated with no replacement package. Versions 4.13.11 and 4.13.12 followed on 2026-09-29 and 2026-09-30, and 4.13.13 landed on 2026-10-04.

Hono adapter packages named in the 4.13.10 notes, read 2026-10-08
Runtime or hostNew packageOld import
Bun@hono/bunhono/bun (deprecated, removed in v5)
Deno@hono/deno (also on JSR)hono/deno
Cloudflare Workers@hono/cloudflare-workershono/cloudflare-workers
AWS Lambda@hono/aws-lambdahono/aws-lambda
Vercel@hono/vercelhono/vercel
Cloudflare PagesNonehono/cloudflare-pages (deprecated)

Why verification does not change

Sume signs <timestamp>.<raw_body> with HMAC-SHA256. The SDK check is async, returns false for a malformed delivery, and never throws. It reads headers from a Headers object, which is what c.req.raw.headers is in Hono.

Read the body once with c.req.text(). If a middleware parses JSON first, the signed bytes are gone.

The handler

This route is the same on every runtime. Only the line that exports or serves the app differs, and that is where the new adapter package comes in.

import { Hono } from "hono";
import { verifyWebhook } from "@sume-com/sdk";

const app = new Hono<{ Bindings: { SUME_COM_WEBHOOK_SIGNING_SECRET?: string } }>();

app.post("/hooks/sume", async (c) => {
  const secret = c.env?.SUME_COM_WEBHOOK_SIGNING_SECRET ?? globalThis.process?.env?.SUME_COM_WEBHOOK_SIGNING_SECRET;
  if (!secret) return c.text("not configured", 500);
  const body = await c.req.text();
  const ok = await verifyWebhook({ body, headers: c.req.raw.headers, secret });
  if (!ok) return c.text("bad signature", 401);
  const event = JSON.parse(body);
  console.log(event.event, event.job_id);
  return c.body(null, 204);
});

export default app;

Migration steps

Do the swap in one commit and send a webhook.test to confirm.

  • Install the package for your runtime and change the import.
  • Pin Hono to 4.13.13 or later; 4.13.11 fixed a serveStatic double-decode security issue.
  • Call POST /v1/webhooks/test-deliveries and check for a 204.
  • Dedupe on job_id; Sume retries up to 10 times.

Entrypoints by runtime

The route code is the same, so the work is in the file that exports the app. On Workers the app is the default export and the platform calls its fetch. On Bun the default export also works with the runtime server. For Deno, Deno.serve(app.fetch) needs no adapter at all. The adapter packages matter when you use their extras, such as static file serving, which is where the 4.13.11 security fix applied.

If you only receive webhooks, you may not need any adapter package, and removing the import is the simplest way to be ready for v5.

Workers read secrets from the environment binding, Bun and Deno from the process environment. The handler above reads both and refuses an empty value. Do not hard-code the secret and do not log it. The dashboard shows a fingerprint of the secret that is safe to compare with the x-sume-webhook-secret-fingerprint header on each delivery.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume