ZenBid Docs

Webhooks

Subscribe to listing, offer, order, payment, and payout events.

Webhooks

Webhook endpoints let downstream systems react to marketplace changes without polling. The beta product keeps the event model intentionally close to the core REST resources so event consumers do not need a second mental model.

Core Routes

RoutePurpose
GET /api/v1/webhooks/endpointsList endpoints for the active organization
POST /api/v1/webhooks/endpointsCreate an endpoint and return the signing secret
PATCH /api/v1/webhooks/endpoints/:idUpdate url, events, description, or status
DELETE /api/v1/webhooks/endpoints/:idRemove an endpoint
GET /api/v1/webhooks/deliveriesInspect stored delivery attempts

Endpoint create, update, and delete routes currently require a signed-in owner, admin, or developer user for the active organization.

Event Types

  • listing.published
  • offer.submitted
  • offer.countered
  • offer.accepted
  • offer.rejected
  • order.created
  • order.paid
  • order.fulfilled
  • order.refunded
  • order.disputed
  • payment.succeeded
  • payment.failed
  • payment.refunded
  • payout.released

Create An Endpoint

{
  "url": "https://example.com/zenbid/webhooks",
  "description": "Marketplace sync endpoint",
  "subscribedEvents": ["order.created", "order.paid", "payout.released"]
}

Endpoint creation returns both:

  • endpoint
  • signingSecret

Store the signing secret immediately. ZenBid does not expose the raw secret again after creation.

Delivery Format

Each webhook request includes:

  • X-ZenBid-Event
  • X-ZenBid-Event-Id
  • X-ZenBid-Timestamp
  • X-ZenBid-Signature

The signature format is:

t=<unix-timestamp>,v1=<sha256-hmac>

ZenBid signs the string <timestamp>.<raw-json-payload> with the endpoint's signing secret.

Delivery Records

Each delivery stores:

  • the event payload
  • delivery status
  • response status
  • attempt count
  • last attempt time
  • next attempt time when delivery failed

That gives beta operators enough visibility to inspect failures and manage follow-up without polling live systems.

Signature Verification

import { verifyZenBidWebhookSignature } from "@zenbid/sdk";

const rawBody = await request.text();
const isValid = verifyZenBidWebhookSignature({
  secret: process.env.ZENBID_WEBHOOK_SECRET!,
  payload: rawBody,
  signatureHeader: request.headers.get("x-zenbid-signature"),
});

if (!isValid) {
  throw new Error("Invalid ZenBid webhook signature");
}