Webhooks

Realtime events for subscriptions, billing, and library changes.

Gummble sends webhooks for subscription lifecycle (via Polar), payment events, and library mutations. All deliveries are signed so you can verify origin without secret rotation drift.

Configuring an endpoint

Set your webhook URL in Settings → Webhooks on gummble.com.

We require:

  • https:// only (no plaintext)
  • TLS 1.2+
  • Endpoint returns 2xx within 10s, else we retry

Verifying signatures

Every delivery has:

X-Gummble-Signature: t=1779555000,v1=hex(sha256(t + "." + body, secret))
X-Gummble-Event:     subscription.created
X-Gummble-Delivery:  evt_01HXY...
function verify(secret, header, rawBody) {
  const [t, v1] = header.split(',').map(p => p.split('=')[1])
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex')
  // timing-safe compare
  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
    && (Date.now()/1000 - Number(t) < 300)
}

Reject deliveries older than 5 minutes — replay protection.

Event types

EventDescription
subscription.createdNew paid subscription started
subscription.updatedPlan, renewal, or status changed
subscription.canceledUser canceled (still active until period end)
subscription.deletedSubscription fully ended
payment.succeededStripe/Polar payment captured
payment.failedPayment attempt failed
app.addedNew app indexed in the library
screen.addedNew screen captured for an existing app

Retry behaviour

Failed deliveries (non-2xx, timeout, TLS error) retry with exponential backoff: 2m, 10m, 30m, 1h, 4h, 8h, 24h. After 7 failures the endpoint is disabled and you get an email.