LBLetBuyy DevelopersWebhook contract
HomeAPIOAuthWebhooksSDKsDashboard

Webhooks

HMAC signing, outbound headers, mandatory compliance topics, and queued retry behavior from the current webhook service.

Signed Delivery Contract

Current outbound app webhook signature behavior.

  • Outbound LetBuyy webhooks use User-Agent: LetBuyy-App-Webhooks/1.0.
  • The signing payload is `${timestamp}.${rawBody}`.
  • The HMAC header is X-LetBuyy-Hmac-SHA256 and the value is versioned as v1=<hex>.
  • X-LetBuyy-Signature is sent as a legacy alias with the same versioned value.
  • Mandatory compliance topics are always added to app webhook subscriptions: customers/data_request, customers/redact, and shop/redact.
  • Merchant/customer compliance producers emit through POST /v1/app-store/compliance/customers/data-request, POST /v1/app-store/compliance/customers/redact, and POST /v1/app-store/compliance/shop/redact.
  • App uninstall emits shop/redact before app webhook subscriptions are disabled, then emits app.uninstalled.
  • Queued delivery retries use exponential backoff from 120 seconds and cap at one hour.

Verification Sketch

Use the exact timestamp and raw request body bytes.

const payload = `${timestamp}.${rawBody}`;
const expected = hmacSha256Hex(signingSecret, payload);
const received = hmacHeader.replace(/^v1=/, "");
const valid = timingSafeEqualHex(expected, received);

LetBuyy sends X-LetBuyy-Hmac-SHA256, X-LetBuyy-Timestamp, X-LetBuyy-Event-ID, and X-LetBuyy-Event-Type.

Topic Requirements

Lifecycle topics and mandatory compliance topics attached to app webhook subscriptions.

TopicCategoryDelivery rulePartner actionSource
app.installedlifecycleCreated during OAuth authorize and direct install flows when webhook definitions exist.Initialize app-side store state, scopes, onboarding, and billing setup using the signed lifecycle payload.services/api-gateway/src/routes/app-store.ts:1230
app.uninstalledlifecycleCreated during uninstall after subscriptions are disabled and install state is revoked.Revoke tokens, stop background work, remove merchant-specific data that is no longer needed, and preserve required audit records.services/api-gateway/src/routes/app-store.ts:1736
customers/data_requestmandatory complianceApp webhook subscriptions always include this topic in event_types; POST /v1/app-store/compliance/customers/data-request emits it to active app-platform subscriptions for the store.Respond to the merchant/customer data export request through the partner app's compliance workflow.services/api-gateway/src/routes/app-store/compliance-routes.ts:129 + packages/app-engine/src/index.ts:150
customers/redactmandatory complianceApp webhook subscriptions always include this topic in event_types; POST /v1/app-store/compliance/customers/redact emits it to active app-platform subscriptions for the store.Delete or anonymize customer personal data held by the partner app.services/api-gateway/src/routes/app-store/compliance-routes.ts:131 + packages/app-engine/src/index.ts:150
shop/redactmandatory complianceApp webhook subscriptions always include this topic in event_types; POST /v1/app-store/compliance/shop/redact emits it explicitly and app uninstall emits shop/redact before app webhook subscriptions are disabled.Delete or anonymize store-level data held by the partner app after store/app lifecycle cleanup.services/api-gateway/src/routes/app-store/compliance-routes.ts:133 + services/api-gateway/src/routes/app-store/install-lifecycle-routes.ts:335

Delivery, Retry, and Failure Rules

Current dispatch, retry, and endpoint behavior from the webhook worker.

RuleCurrent behaviorDeveloper actionSource
Target URLProduction webhook targets must be HTTPS. Localhost HTTP is accepted only when the webhook service is not running in production mode.Use HTTPS callbacks for real app installs and reserve localhost HTTP for local test environments.services/webhook-service/src/app-lifecycle-dispatch.ts:35 + :79
Signing payload and headersThe service signs `${timestamp}.${rawBody}`, sends X-LetBuyy-Hmac-SHA256 as v1=<hex>, and also sends X-LetBuyy-Signature as a legacy alias.Verify against the raw request body bytes and strip the optional v1= prefix before timing-safe comparison.services/webhook-service/src/app-lifecycle-dispatch.ts:52 + :57 + :90
Delivery body and correlationThe POST body is { id, event_type, created_at, payload }. Headers include event ID/type, request ID, trace ID, timestamp, user-agent, and both signature headers.Persist X-LetBuyy-Event-ID for idempotency and keep X-LetBuyy-Request-ID or X-LetBuyy-Trace-ID with support logs.services/webhook-service/src/app-lifecycle-dispatch.ts:83 + :93
Endpoint response handlingAny 2xx response marks delivery successful. Non-2xx responses record a response preview and error `Webhook endpoint returned HTTP <status>`; fetch failures have null status.Return 2xx only after the event is durably accepted. Treat duplicate event IDs as already processed.services/webhook-service/src/app-lifecycle-dispatch.ts:109 + :115 + :121
Retry scheduleFailed queued deliveries use exponential backoff from 120 seconds, bound attempts to 0-8, and cap retry delay at 3600 seconds.Expect retries after transient failures and make callback processing idempotent by event ID.services/webhook-service/src/index.ts:246
Queue claim and finalizationThe dispatcher claims work through claim_webhook_deliveries, calls complete_webhook_delivery on success, and fail_webhook_delivery with p_retry_seconds on failure.Do not rely on immediate delivery ordering; use event IDs and timestamps for reconciliation.services/webhook-service/src/index.ts:788 + :810 + :818
Internal dispatch routesPOST /app-lifecycle/dispatch and POST /webhook-deliveries/dispatch require X-LetBuyy-Internal-Secret and are service/internal surfaces.[SKIP — NEEDS BACKEND/SDK] Do not call these routes from partner apps; public webhook test sender tooling is not present yet.services/webhook-service/src/index.ts:748 + :842
Subscription event filterLifecycle and compliance dispatch sends only to subscriptions whose event_types include the current event. Planned app subscriptions append mandatory compliance topics to every configured webhook.Register the lifecycle topics your app needs and implement the mandatory compliance topics emitted by the platform.services/api-gateway/src/routes/app-store/shared.ts:484 + packages/app-engine/src/index.ts:1430
Compliance producer routesPOST /v1/app-store/compliance/customers/data-request, /customers/redact, and /shop/redact require merchant auth, store ownership, an idempotency key, and app webhook delivery configuration when active app subscriptions exist.Use these routes from merchant/customer compliance workflows and dedupe events by X-LetBuyy-Event-ID on the partner callback.services/api-gateway/src/routes/app-store/compliance-routes.ts:129

Delivery Examples

Headers, body shape, and signing input from the current webhook dispatcher.

Outbound Headers

Headers sent to partner HTTPS callbacks for app lifecycle and queued delivery.

services/webhook-service/src/app-lifecycle-dispatch.ts:94
POST https://partner.example/letbuyy/webhooks
Content-Type: application/json
User-Agent: LetBuyy-App-Webhooks/1.0
X-LetBuyy-Event-ID: event_id
X-LetBuyy-Event-Type: app.installed
X-LetBuyy-Request-ID: request_id
X-LetBuyy-Trace-ID: trace_id
X-LetBuyy-Timestamp: 1780440300
X-LetBuyy-Hmac-SHA256: v1=<hex_digest>
X-LetBuyy-Signature: v1=<hex_digest>

Outbound Body

The body signed by the HMAC helper is the exact JSON payload delivered to the callback.

services/webhook-service/src/app-lifecycle-dispatch.ts:83
{
  "id": "event_id",
  "event_type": "app.installed",
  "created_at": "2026-06-03T04:05:00.000Z",
  "payload": {
    "installation_id": "installation_id",
    "app_id": "app_id",
    "store_id": "site_id"
  }
}

Signing Payload

The HMAC input is timestamp, a dot, and the unmodified raw request body.

services/webhook-service/src/app-lifecycle-dispatch.ts:57
const signingPayload = `${timestamp}.${rawBody}`;
const expectedHex = hmacSha256Hex(signingSecret, signingPayload);
const receivedHex = hmacHeader.replace(/^v1=/, "");
const valid = timingSafeEqualHex(expectedHex, receivedHex);

Webhook Service Endpoints

Developer-facing callback contract plus internal dispatch routes that power delivery.

MethodRouteAuthStatusCurrent behaviorSource
POSThttps://webhooks.letbuyy.store/app-lifecycle/dispatchinternalAVAILABLEInternal gateway-to-webhook-service route that signs and dispatches app lifecycle callbacks.services/webhook-service/src/index.ts:748
POSThttps://webhooks.letbuyy.store/webhook-deliveries/dispatchinternalAVAILABLEInternal dispatcher for queued webhook delivery rows with retry scheduling.services/webhook-service/src/index.ts:842
POSTPartner HTTPS callback URLHMAC signatureAVAILABLELetBuyy sends app lifecycle and queued webhooks with X-LetBuyy-Hmac-SHA256, X-LetBuyy-Timestamp, event ID, event type, request ID, and trace ID headers.services/webhook-service/src/app-lifecycle-dispatch.ts:86