← Blog

Claude API Webhook Setup Guide (Build It Yourself)

2026-09-23 · 5 min read · SubToAPI Team

If you're searching for a "Claude API webhook setup guide," the first thing to know is that Anthropic's Claude API doesn't have native webhooks. There's no dashboard toggle where you register a callback URL and Claude pushes events to it the way Stripe or GitHub do. Claude's API is a synchronous request/response model: you send a message, you get a message back (or a stream of chunks), and that's the end of the interaction from Anthropic's side.

What people actually need when they search this term is a way to get webhook-like behavior around Claude calls — notify a Slack channel when a long-running generation finishes, trigger a downstream job once a summary is ready, or push results into another system without polling. That's entirely achievable, but you have to build the webhook layer yourself, on top of your own backend. This guide walks through exactly how to do that.

Why Claude API Doesn't Have Native Webhooks

Claude API calls typically complete in seconds, not hours. Anthropic's model is built around a request-response or streaming pattern:

Because there's no long-running background job on Anthropic's infrastructure that outlives your HTTP request, there's nothing for a webhook to report on later. Webhooks make sense for asynchronous systems (a payment settling, a build finishing hours later). Claude's completions don't need that model — but your application around Claude often does, especially if you're batching requests, running agentic loops, or processing large documents.

The Pattern: Your Own Webhook Relay

The standard approach is a three-part pipeline:

  1. Your backend receives a job (e.g., "summarize this 40-page PDF").
  2. Your backend calls Claude, waits for or streams the result.
  3. Once done, your backend fires an HTTP POST to a webhook URL you control (or that a downstream service registered with you).

This keeps Claude itself simple and puts the async logic where it belongs — in your own service layer.

Step 1: Queue the Job

Don't call Claude directly from a request handler if the job might take a while or you want retry logic. Push it onto a queue (BullMQ, SQS, a simple database table with a status column — anything works).

// enqueue.js
async function enqueueClaudeJob(payload, webhookUrl) {
  await db.jobs.insert({
    status: "pending",
    payload,
    webhookUrl,
    createdAt: new Date(),
  });
}

Step 2: Worker Calls Claude and Delivers the Webhook

A separate worker process picks up pending jobs, calls the Claude API, and on completion sends the result to the registered webhook URL.

// worker.js
import fetch from "node-fetch";

async function processJob(job) {
  const response = await fetch("https://api.anthropic.com/v1/messages", {
    method: "POST",
    headers: {
      "x-api-key": process.env.ANTHROPIC_API_KEY,
      "anthropic-version": "2023-06-01",
      "content-type": "application/json",
    },
    body: JSON.stringify({
      model: "claude-sonnet-4-5",
      max_tokens: 1024,
      messages: job.payload.messages,
    }),
  });

  const result = await response.json();

  // Fire the webhook
  await fetch(job.webhookUrl, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      jobId: job.id,
      status: "completed",
      result,
    }),
  });

  await db.jobs.update(job.id, { status: "completed" });
}

This gives you a real webhook: the caller registers a URL, your system does the work, and you POST the result when it's ready — exactly the UX people expect from "Claude API webhooks" even though Anthropic isn't the one sending them.

Step 3: Make Webhook Delivery Reliable

Webhook delivery fails — endpoints go down, networks time out. Build in retries with exponential backoff and log every delivery attempt:

async function deliverWebhook(url, payload, attempt = 1) {
  try {
    const res = await fetch(url, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(payload),
    });
    if (!res.ok) throw new Error(`Webhook returned ${res.status}`);
  } catch (err) {
    if (attempt < 5) {
      await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
      return deliverWebhook(url, payload, attempt + 1);
    }
    console.error("Webhook delivery failed permanently", err);
  }
}

Also sign your payloads with an HMAC secret so receivers can verify the webhook actually came from your system, not a spoofed request.

Handling Streaming + Webhooks Together

If you're streaming Claude's response to a UI in real time but also want a webhook fired once the full response lands (for logging, indexing, or triggering a second workflow), keep both paths open: stream chunks to the client as they arrive, buffer the full text server-side, and fire the webhook once the stream closes. Don't try to webhook per-token — that defeats the purpose of a completion event and will flood receivers with noise.

If you're building this on SubToAPI, the streaming endpoint works the same way — you consume server-sent events from /v1/messages with stream: true, and once the stream ends you trigger your own webhook logic on top. SubToAPI doesn't send webhooks itself, but it does give you application-scoped API keys (sub_live_...) and per-key usage metadata, which is useful for tracking which key/job triggered which webhook delivery when you're running multiple services against the same Claude access. See the streaming docs and quickstart for the request format.

Common Mistakes to Avoid

Questions

Does the Claude API support native webhooks? No. Anthropic's API is request/response (or streaming) only. Any webhook behavior has to be built in your own application layer around the API calls.

How do I get notified when a long Claude job finishes? Run the call from a background worker (queue-based or serverless), then have that worker POST the result to a webhook URL once the response completes — the pattern described above.

Can SubToAPI send webhooks for Claude responses? Not currently — SubToAPI provides API keys, streaming, tool use, and usage metadata over /v1/messages. You'd build the webhook relay on top of those calls, the same way you would with direct Anthropic access. See /docs for the full request reference.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →