OpenAI webhooks that survive a 45-second handler.

Your handler is doing real work, RAG, another model call, a DB transaction. OpenAI gives it a few seconds. AnyHook returns 200 in about 1s and lets your handler finish on its own time.

The timing problem

OpenAI's background responses, batch jobs and fine-tuning jobs all report back over HTTP and expect a 2xx within a few seconds, then retry for up to 72 hours. The moment your handler does something interesting, chain a second model call, do a vector search, hit Stripe, you blow past it.

When you blow past it, OpenAI retries. Your handler runs again. Now you're paying for tokens twice and your downstream system sees duplicates. The fix is not a longer timeout; it's a separate ack-and-process pattern.

72h
How long OpenAI keeps retrying a missed webhook
45-90s
Typical agent-in-a-handler latency
2×
Token cost when the retry fires
about 1s
AnyHook edge ack time (median, 1.1s p95)

Drop-in replacement: change the webhook URL

Your existing handler doesn't need to change. AnyHook acks OpenAI in about 1s at the edge, then forwards the verified payload to your endpoint with full retry, replay, and event log.

// 1. Point OpenAI's webhook URL at your AnyHook inbound:
//    https://in.anyhook.net/{user-slug}/{app-slug}
//
// 2. Keep your existing handler, it now has all the time it needs.
//    AnyHook re-signs every delivery with AnyHook-Signature.

import OpenAI from "openai";
import { verifyWebhook } from "anyhook-verify";

const openai = new OpenAI();

export async function POST(req: Request) {
  const ok = await verifyWebhook(req, process.env.ANYHOOK_SIGNING_SECRET!);
  if (!ok) return new Response("invalid signature", { status: 401 });

  // OpenAI's own event, byte for byte: { type: "response.completed", data: { id }, ... }
  const event = await req.json();
  if (event.type !== "response.completed") return new Response("ok");
  const response = await openai.responses.retrieve(event.data.id);

  // Run anything here. AnyHook already returned 200 to OpenAI.
  // If you fail, AnyHook retries with backoff (up to 10 attempts on Scale).
  await ragPipeline(response);     // 25s
  await secondModelCall(response); // 18s
  await persistResult(response);   // 2s

  return new Response("ok", { status: 200 });
}

Questions teams ask

Do I lose OpenAI's signature verification?
No. OpenAI signs with the Standard Webhooks scheme (webhook-id, webhook-timestamp, webhook-signature). Set the app's source to Standard Webhooks and paste the webhook's signing secret (whsec_...): AnyHook checks it at the edge and rejects forgeries, then re-signs every delivery to your endpoint with AnyHook-Signature.
What happens if my handler is down for an hour?
AnyHook queues the event and retries on exponential backoff: up to 3 attempts on Free, 5 on Pro, 10 on Scale. Every attempt is logged and replayable from the dashboard. OpenAI sees one 200 and moves on.
Which OpenAI events does this cover?
Whatever OpenAI sends by webhook: background responses (response.completed and its failed, cancelled and incomplete siblings), batch jobs, fine-tuning jobs and eval runs. Streaming is not a webhook: it is a stream your code reads directly, so it never passes through AnyHook.

Change one URL. Keep your OpenAI handler.

Free tier covers 10K events / month. No SDK: point OpenAI at your AnyHook inbound URL.