OyeChats
FeaturesSolutionsIntegrationsPricingDocsBlogContact us
All posts
Engineering8 min read

Webhook best practices for chat platforms, from a team that ships them

How to design webhooks that stay reliable under retries, spikes, and partner outages, without turning into a support nightmare.

PL
Platform Team
Engineering · May 3, 2026

Webhooks look simple on a whiteboard. Something happens on our side, we send a POST to your URL. In production, the same feature is where roughly a third of integration bugs quietly live. Retry storms, delivery gaps, silent signature mismatches, and endpoints that return two hundred OK while doing nothing at all. The rules below are what we have learned running webhooks across thousands of bots.

Sign every payload, and pin the signature scheme

Every webhook we send carries an HMAC SHA 256 signature over the raw request body, computed with a secret unique to the receiver. Two things matter here. First, sign the raw bytes, not the parsed JSON, because any JSON reserialisation on either side breaks verification. Second, put the scheme identifier in the header, so future rotations do not require a coordinated release.

X-OyeChats-Signature: v1=8f2a1c93b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1
X-OyeChats-Timestamp: 1739299200

The timestamp is not decoration. Verifiers should reject any request more than five minutes old, which kills replay attacks and also catches misconfigured servers whose clocks have drifted.

Retry with exponential backoff and a hard cap

If your receiver returns anything other than a two hundred status, we retry. Retries follow exponential backoff with jitter, and we cap the total window at twenty four hours. After that we mark the delivery as failed and expose it in the admin dashboard for manual replay.

  • Return a two hundred as soon as you have durably enqueued the payload. Do the real work in a background job.
  • Never retry from your side too. The sender is already retrying, and duplicate retries lead to duplicate side effects.
  • Log the delivery id so support can trace a specific event across both systems.

Make every event safely retriable

The sender does not know whether your two hundred came before or after the crash. The only safe assumption is that any event might arrive twice. Every event carries a stable delivery id and a stable event id. Store the event id on the receiver, check it before applying side effects, and skip if it has already been processed.

Send small, coherent events

Large batched payloads are tempting because they cut request volume. They also make retries expensive, encourage partial failure handling that nobody actually writes, and force the receiver to parse events they may not care about. We prefer one event per business fact. A new chat session, a new message, a status change. The receiver filters what it wants.

Observability the receiver can trust

Every webhook we send is inspectable in the admin dashboard. The receiver sees the raw payload, the response status, the response body, the delivery timestamps, and every retry attempt with its reason. When integrations break at three in the morning, that is the difference between a five minute fix and a two hour support thread.

None of this is exotic. It is a small collection of habits that pay off the first time a downstream system has a bad day, which will happen sooner than you expect.

WebhooksIntegrationsReliability

See it on your own site

OyeChats answers every visitor from your own docs, scores their intent as they chat, and routes the buyers to your team. Free to start — live in under 10 minutes.