← Blog

Claude API Webhook Integration Setup Guide

2026-10-05 · 5 min read · SubToAPI Team

If you searched for "claude api webhook integration setup," you're probably trying to connect an incoming event — a form submission, a GitHub push, a Stripe payment, a Slack message — to a Claude-powered action, and get the result back out automatically. The thing worth knowing upfront: the Claude API itself does not emit webhooks. It's a synchronous request/response HTTP API — you send a message, you get a completion back (or a stream of chunks). There's no event bus on Anthropic's side that calls your server when something happens.

That means "webhook integration" with Claude almost always refers to one of two patterns you build yourself: (1) an inbound webhook receiver that triggers a Claude API call when an external event arrives, or (2) an outbound callback that notifies another system once Claude has finished generating a response. This guide covers both, with a working setup you can copy.

The two integration patterns

Pattern A — event triggers Claude: Stripe, GitHub, Twilio, or your own app POSTs a webhook to your server. Your server validates it, extracts the relevant data, and calls the Claude API to summarize, classify, draft a reply, or take some action based on that payload.

Pattern B — Claude's output triggers a webhook: A long-running or batch job calls Claude, and once the completion is ready, your server POSTs the result to a callback URL — useful for async pipelines where the original caller doesn't wait on the HTTP connection.

Most real integrations combine both: receive an event, call Claude, send the result onward.

Step 1: Build the webhook receiver

Start with a minimal endpoint that accepts the incoming event and verifies it's genuine before doing anything expensive. Never call an LLM on unverified input from the public internet.

const express = require("express");
const crypto = require("crypto");
const app = express();

app.use(express.raw({ type: "*/*" }));

function verifySignature(req, secret) {
  const signature = req.headers["x-webhook-signature"];
  const expected = crypto
    .createHmac("sha256", secret)
    .update(req.body)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex")
  );
}

app.post("/webhooks/incoming", (req, res) => {
  if (!verifySignature(req, process.env.WEBHOOK_SECRET)) {
    return res.sendStatus(401);
  }
  // Acknowledge fast, process async
  res.sendStatus(202);
  handleEvent(JSON.parse(req.body.toString()));
});

Respond quickly (202 Accepted) and do the Claude call asynchronously. Most webhook providers retry aggressively if you don't respond within a few seconds, and a Claude completion can easily take longer than that — especially with longer prompts or tool use.

Step 2: Queue the work, don't block the request

Put the event on a queue (SQS, Redis, BullMQ, or even a simple in-process job table) rather than calling Claude directly inside the webhook handler. This protects you from:

async function handleEvent(payload) {
  const jobId = payload.id || crypto.randomUUID();
  await queue.add("process-with-claude", { jobId, payload });
}

Use the event's own ID as an idempotency key so retried deliveries don't produce duplicate Claude calls and duplicate side effects.

Step 3: Call the Claude API from the worker

The worker picks up the job and makes the actual completion request. If you're routing through SubToAPI instead of managing Anthropic credentials directly, the call looks like this:

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-5",
    max_tokens: 1024,
    messages: [
      { role: "user", content: `Summarize this event: ${JSON.stringify(payload)}` }
    ]
  })
});

const result = await response.json();

SubToAPI issues per-application sub_live_... keys and tracks usage metadata per key, which matters for webhook-driven workloads: you can see exactly how many tokens a given integration (e.g., "github-pr-summarizer") is consuming without digging through Anthropic's own billing dashboard. Full request/response shape is in /docs/messages.

Step 4: Send the result onward

Once you have the completion, POST it to wherever it needs to go — a Slack incoming webhook, your own callback URL, a database write, or a ticketing system.

await fetch(payload.callbackUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jobId,
    status: "completed",
    output: result.content[0].text
  })
});

If the downstream system needs to show progress rather than wait for a single blob, consider streaming the Claude response instead of batching it — see /docs/streaming for the SSE event format.

Step 5: Handle failures and retries

Webhook pipelines fail in predictable ways. Build for them from day one:

Step 6: Secure the whole chain

Putting it together

A working Claude webhook integration is really three independent pieces: a fast, signature-verified receiver; a queue that decouples receiving from processing; and a worker that calls the Claude API and forwards the result. None of these pieces require anything special from Anthropic's side — they're standard backend patterns applied to an LLM call. If you want the API layer handled for you — key management, usage tracking, streaming — start with /signup, check /docs/quickstart for the first call, and /pricing for plan details.

Questions

Does the Claude API support native webhooks? No. It's a request/response HTTP API with optional streaming. Any webhook behavior — triggering a call or notifying on completion — has to be built on your own server.

Should I call Claude directly inside my webhook handler? No. Acknowledge the webhook quickly, queue the work, and call Claude from a background worker. This avoids timeouts and duplicate processing from retried deliveries.

How do I avoid duplicate Claude calls from retried webhooks? Use the event's own ID (or a hash of its payload) as an idempotency key, and check it against a processed-jobs store before enqueuing or calling the Claude API again.

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 →