API guide
Receive and verify webhook events
Subscribe to what you need
Create an HTTPS webhook endpoint and choose event types. Test and live endpoints are separate. Save the signing secret securely; during secret rotation, verify against the active secret while the overlap completes.
Events contain id, version (currently 1), type, at, livemode and data. The OpenAPI components define the envelope and event data schemas. Return 2xx only after durable acceptance. Delivery is at least once: deduplicate by id and tolerate duplicates or events arriving out of order.
Verify before parsing
Buddy-Signature contains t=<unix timestamp> and one or more v1=<hex signature> entries. Compute HMAC-SHA256(secret, timestamp + '.' + raw body). Use a constant-time comparison against any v1 value and reject timestamps more than five minutes from your clock.
Verify the exact raw bytes before parsing JSON. Do not stringify an already-parsed object; whitespace and key order affect the signature. Keep your server clock synchronized.
Recover failed deliveries
The dashboard shows delivery attempts and lets you resend after fixing your receiver. Buddy retries failures with backoff and pauses delivery after three days of failures. A 410 Gone response disables the endpoint immediately. Both are reversible: fix the receiver, then PATCH the endpoint with status: enabled. Events are retained for 30 days, including events emitted while delivery is disabled. List matching events with GET /webhook_endpoints/{id}/events?since=RFC3339_TIMESTAMP and follow cursor pagination. Resend each event through POST /webhook_endpoints/{id}/events/{event_id}/resend. Deduplicate by event ID so replay cannot apply the same action twice.
Related API operations
Verification examples
Choose your language and verify the original request body before processing an event.
import { Buddy } from "@usebuddy/sdk";
// Call this before your framework parses the body. Persist event.id in your
// durable deduplication store before processing and returning a 2xx response.
export async function verifyBuddyRequest(request: Request) {
const signature = request.headers.get("Buddy-Signature");
const secret = process.env.BUDDY_WEBHOOK_SECRET;
if (!signature || !secret) throw new Error("Missing signature or signing secret");
const rawBody = new Uint8Array(await request.arrayBuffer());
const event = Buddy.webhooks.verify(rawBody, signature, secret);
if (!event || typeof event !== "object" || !("id" in event) || typeof event.id !== "string") {
throw new Error("Invalid webhook event");
}
return event;
}