Webhooks & bots

Run webhooks, Slack bots & automation without a server.

The integration logic is usually 50 lines. The infrastructure shouldn't become the project. Deploy a handler, get an HTTPS endpoint, and ship the workflow.

The webhook problem

“Just set up a webhook endpoint,” the docs say. Then you get pulled into SSL certificates, hosting, process monitoring, and log plumbing.

Where do you host it?
How do you handle SSL?
How do you verify requests?
Where do logs go?
What about retries?
What if traffic spikes?

What should be a 15-minute integration becomes a weekend infrastructure project.

Why this matters

Webhooks are small code. They deserve small infrastructure.

Webhooks are five steps: receive a POST, verify it, process data, respond quickly, optionally trigger follow-up actions.

Traditional deployment treats that like a microservice. LoveKit treats it like what it is: an event handler.

No server

Deploy handlers, not infrastructure.

HTTPS endpoint

Use it in Stripe/GitHub/Slack.

Built-in logs

Debug without guessing.

Ship fast

Stay in flow while you build.

Integration lab

Copy a pattern. Ship the integration.

Pick an integration. See what the handler needs to do, plus a starter structure you can adapt.

Deploy your first webhook

Stripe payment webhooks

Receive events, verify signatures, update your DB, and respond fast. The logic is small; the hosting usually isn’t.

Receive webhook eventsVerify Stripe signatureUpdate subscription stateReturn 2xx quickly

Starter code

See MVP backends
import crypto from "node:crypto";

type Payload = { [key: string]: any };

export async function handler(payload: Payload) {
  // 1) Verify signature (illustrative)
  const sig = payload.headers?.["stripe-signature"];
  const rawBody = payload.rawBody ?? JSON.stringify(payload.body ?? {});
  const expected = crypto
    .createHmac("sha256", process.env.STRIPE_WEBHOOK_SECRET)
    .update(rawBody)
    .digest("hex");

  if (!sig || !sig.includes(expected)) {
    return { status: 401, message: "Invalid signature" };
  }

  // 2) Handle event types
  const type = payload.body?.type;
  if (type === "payment_intent.succeeded") {
    // update user subscription, send email, etc.
  }

  return { status: "OK", message: "Successful" };
}

Slack bot kit

A complete standup bot without a server.

Three functions. Three endpoints. Daily reminder + modal submission + summary posting.

Send daily standup message

Triggered by an external scheduler for now (native cron coming soon). Posts a message with a button.

export async function handler(_: any) {
  await sendSlackMessage({
    channel: "#engineering",
    text: "Good morning! Time for standup",
    blocks: [
      { type: "section", text: { type: "mrkdwn", text: "Time for daily standup!" } },
      {
        type: "actions",
        elements: [
          { type: "button", text: { type: "plain_text", text: "Submit Standup" }, action_id: "open_standup_modal" },
        ],
      },
    ],
  });

  return { status: 200 };
}

Best practices

Production patterns for webhooks & bots

These are the habits that keep integrations stable when providers retry, payloads change, and you need to debug quickly.

Always verify request signatures

Stripe, GitHub, Slack, and Discord sign requests. Verification prevents malicious triggers.

import crypto from "node:crypto";

export function verifyWebhookSignature(secret: string, signature: string, body: string) {
  const hmac = crypto.createHmac("sha256", secret);
  hmac.update(body);
  const expected = hmac.digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Fit

When LoveKit is perfect for webhooks and bots

If your bot is request/response and your work completes quickly, functions are a great fit.

If you need persistent connections or long-running processes, you may want a different architecture.

Great for

Stripe webhooksGitHub automationSlack commands + interactionsDiscord commandsTwilio / SendGrid webhooksScheduled tasks (external trigger)

Not ideal for

Persistent connectionsReal-time bidirectional streamsLong-running jobs (>60s)Complex shared state across requests

Frequently asked questions

How do I deploy a webhook endpoint?

Write a handler function, deploy it, and use the HTTPS endpoint in Stripe/GitHub/Slack. No server provisioning or SSL setup required.

What if my provider retries events?

Assume at-least-once delivery. Use idempotency (event ids), log aggressively, and treat retries as normal.

Can I build Slack bots with multiple endpoints?

Yes. Use separate functions/endpoints for slash commands, interactions, and submissions so each stays simple and testable.

Where should I start if I'm currently on AWS Lambda?

Start with your smallest webhook handler. If you want a direct comparison, read the AWS Lambda alternative page. AWS Lambda alternative.

Ready to turn your code into an API?

No credit card required. Deploy your first function in under a minute.

Get started freeServerless · No infra · Developer-first