Skip to main content
Wildo.ai Coming soon

Events and external data

Deliver verifiable events to customer endpoints

Send signed event payloads with stable delivery identities, retry handling and a customer-visible delivery record.

The receiver verifies a signed event, deduplicates its delivery identity and then handles it.

Deliver verifiable events to customer endpoints

Customers can register endpoints that receive events from the application. Wildo signs each delivery, records its outcome and retries failures according to a shared delivery policy.

The receiving system can verify where a message came from, check the payload bytes and recognize repeated attempts. Administrators can inspect each endpoint delivery’s attempt count and latest outcome, then retry a delivery that needs attention.

Example — Process one event despite a retry

A receiver accepts an event but its response is lost. When delivery is attempted again, the same delivery identifier lets the receiver recognize the event and avoid repeating its business effect.

For engineers

Create the scoped webhook configuration, enable it and add enabled HTTPS endpoints. Resource operations must emit the matching machine-notification channel. Signing keys and the delivery worker must be available; putting Webhooks in the Settings Hub only exposes administration, not the backend prerequisites.

A delivery has a stable ID across attempts. The worker signs a fresh token for each attempt and sends it in x-wildo-webhook-signature. Read the current applicationPublicKeyPem from the webhook configuration; a rotation changes the verification key, so do not hardcode a deployment-specific key identifier.

This selected contract from m2m-webhook-delivery-contract.shared.ts states the signed claim settings and payload hash algorithm:

  signature: {
    issuer: APPLICATION_JWT_ISSUER,
    audience: 'WEBHOOK',
    expiresIn: '6h',
  },
  /** Algorithm of the `bodyHash` claim: a hex digest of the exact raw request bytes. */
  bodyHashAlgorithm: 'sha256',
  /** Status codes (besides 5xx and transport failures) that schedule another attempt. */
  retryableHttpStatuses: [408, 429],

Verify the signature with the application’s key while pinning ES256, the expected issuer and audience. Check expiry, recompute SHA-256 over the exact raw request bytes and compare the signed bodyHash. Only then deserialize and act. Use jti as the delivery deduplication key; storing successful processing atomically with the business effect is the receiver’s responsibility.

This Node.js receiver example uses jsonwebtoken. Pass a Headers object, the unmodified request body as a Buffer, and the public key obtained from the trusted application configuration. Keep body-parser middleware from replacing those bytes with reserialized JSON.

import jwt from 'jsonwebtoken';
import { createHash } from 'node:crypto';

function verifyDelivery(headers, rawBody, applicationPublicKeyPem) {
  const token = headers.get('x-wildo-webhook-signature');
  if (!token) throw new Error('Missing webhook signature');

  const claims = jwt.verify(token, applicationPublicKeyPem, {
    algorithms: ['ES256'],
    issuer: 'wildo-application',
    audience: 'WEBHOOK',
  });

  const bodyHash = createHash('sha256').update(rawBody).digest('hex');
  if (typeof claims !== 'object' || claims.bodyHashAlg !== 'sha256'
      || claims.bodyHash !== bodyHash || !Number.isInteger(claims.exp)
      || typeof claims.jti !== 'string' || !claims.jti) {
    throw new Error('Invalid webhook claims or body');
  }
  return { deliveryId: claims.jti, synthetic: claims.synthetic === true, event: JSON.parse(rawBody.toString('utf8')) };
}

Only call the business handler after this succeeds. If synthetic is true, acknowledge the verified probe without applying a business effect. Otherwise, store deliveryId with the business effect in one transaction; acknowledge an already processed ID without applying the effect again. A retry carries the same ID with a freshly signed token. This helper verifies a delivery; the receiver’s transaction and HTTP acknowledgement remain application-specific.

Understand acknowledgements and retries

The delivery contract allows five total attempts, with retry delays of one minute, five minutes, thirty minutes and two hours. A 2xx response completes delivery. Transport failures, 5xx, 408 and 429 are retryable; redirects are reported rather than followed. The request timeout is thirty seconds and captured response text is bounded.

Receiver responseDelivery consequence
2xxAccepted by the receiver
408, 429 or 5xxRetry according to the remaining attempt budget
Redirect or other non-retryable 4xxTerminal classification rather than automatic redirection
Connection failureRecorded transport failure and retry policy

One delivery record is created for each destination endpoint. Retries update that record’s attempt count, last and next attempt times, and latest response or failure; they do not create a separate response history for every attempt. Administrative retry requeues the delivery, and date-bounded cleanup removes eligible terminal records. A successful delivery establishes receiver acknowledgement, not proof that the receiver completed its own downstream workflow.

Use HTTPS. The current endpoint contract also admits HTTP, but a signature does not encrypt payloads in transit. The outbound-target guard and redirect policy apply to this path; request safety explains their exact boundary.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.