Skip to main content

Webhook Event Log and Replay

The gateway persists outbound webhook events and their delivery attempts so operators and integrators can inspect failures, replay events, and manage retention without digging directly through service logs.

This page describes the persisted webhook-event surface, the difference between event replay and DLQ retry, and the SDK helpers exposed from the normal admin clients.

Core API surfaces

PurposeEndpoint
List persisted eventsGET /api/v1/webhook-events
Get one eventGET /api/v1/webhook-events/{eventId}
List delivery attempts for an eventGET /api/v1/webhook-events/{eventId}/deliveries
Replay an event to active subscriptionsPOST /api/v1/webhook-events/{eventId}/replay
Retry one DLQ delivery rowPOST /api/v1/webhook-deliveries/{deliveryId}/retry
Read self-scoped retention configGET /api/v1/webhook-events/retention
Update self-scoped retention configPUT /api/v1/webhook-events/retention
Admin list retention overridesGET /api/v1/admin/webhook-events/retention
Admin update one org retention overridePUT /api/v1/admin/webhook-events/retention/{organizationId}

Replay vs. DLQ retry

These two actions are related but not interchangeable.

Replay an event

Use event replay when you want to enqueue delivery again from the persisted event record.

  • Endpoint: POST /api/v1/webhook-events/{eventId}/replay
  • Typical use: replay the event to every active subscription, or to a filtered subset of subscriptions
  • Result: new delivery attempt rows are queued for that event

Retry a DLQ delivery

Use DLQ retry when a specific delivery row already failed all automatic attempts and was marked DLQ_PENDING or DLQ_EXHAUSTED.

  • Endpoint: POST /api/v1/webhook-deliveries/{deliveryId}/retry
  • Typical use: the merchant fixed their endpoint and you want to re-drive the exact failed delivery row
  • Result: the gateway resets that delivery row back into the delivery worker

Rule of thumb:

  • if you are operating from an event-centric view, use replay
  • if you are operating from a delivery-row / DLQ view, use retry

SDK helpers

The persisted-event surface is exposed from the normal admin clients in both SDKs.

TypeScript

import { GatewayAdminClient } from '@gateway/sdk'

const client = new GatewayAdminClient({
environment: 'staging',
tokenProvider: async () => await firebaseUser.getIdToken(),
})

const details = await client.webhookEvents.getDetails('evt_123')

// Replay only failed / DLQ deliveries for the event.
await client.webhookEvents.replayFailedDeliveries(details.event.id)

// Or replay a specific subset of prior delivery rows.
await client.webhookEvents.replayDeliveries(details.event.id, {
deliveryIds: details.deliveries.filter((delivery) => delivery.status === 'FAILED').map((delivery) => delivery.id),
})

// Retry one DLQ delivery row directly.
await client.webhookEvents.retryDeliveryFromDlq('del_456')

const retention = await client.webhookEvents.findRetentionConfigForOrganization('org_123')

Kotlin

import com.myriad.gateway.GatewayAdminClient
import com.myriad.gateway.GatewayConfig

suspend fun operateWebhooks() {
val client = GatewayAdminClient(GatewayConfig("client-id", "client-secret"))

val details = client.webhookEvents.getDetails("evt_123")

client.webhookEvents.replayFailedDeliveries(details.event.id)

client.webhookEvents.replayDeliveries(
eventId = details.event.id,
deliveryIds =
details.deliveries
.filter { it.status == "FAILED" }
.map { it.id }
.toSet(),
)

client.webhookEvents.retryDeliveryFromDlq("del_456")

val retention = client.webhookEvents.findRetentionConfigForOrganization("org_123")
client.close()
}

Delivery diagnostics

Persisted delivery rows can include:

  • delivery status
  • HTTP status from the destination endpoint
  • attempt count
  • last error message
  • allowlisted response headers (lastResponseHeaders)
  • replay lineage (replayOfDeliveryId)

That data is the first place to look before jumping to raw service logs.

Correlation IDs inside received webhook handlers

If your receiver wants a durable way to map a received webhook back to gateway traces or support investigations, use the verifier helpers that preserve the delivery correlation id.

  • TypeScript: WebhookVerifier.verifyDelivery(...)
  • Kotlin: WebhookVerifier.verifyDelivery(...)

Those helpers return the decoded event plus a correlationId extracted from traceparent, X-Cloud-Trace-Context, or X-Request-Id headers when present.