Hydrant API

Webhooks

Being told when an enrichment or a batch ends.

Give a webhook_url when you start an enrichment or a batch, and we post to it when it ends.

Messages

Messages follow Standard Webhooks, so any of its libraries can check them. Each has three headers:

  • webhook-id: the same on every attempt of one message, so you can drop repeats;
  • webhook-timestamp: when the attempt was made, in Unix seconds;
  • webhook-signature: v1, and the base64 HMAC-SHA256 of {id}.{timestamp}.{body}.

The body is {"type", "timestamp", "data"}. type is enrichment.succeeded, enrichment.failed or batch.completed, and data is the enrichment or batch, as GET gives it.

The secret

Each workspace signs with its own secret. Make it in the dashboard's Webhooks page: it starts with whsec_ and is shown once. A workspace with no secret can't take a webhook_url: the request is a 409 webhook_secret_missing. While a rotated secret overlaps its replacement, the header carries a signature for each.

import { Webhook } from "standardwebhooks";

const webhook = new Webhook(process.env.HYDRANT_WEBHOOK_SECRET!);
// Throws unless the signature is ours and the timestamp recent.
const message = webhook.verify(rawBody, {
  "webhook-id": request.headers.get("webhook-id")!,
  "webhook-timestamp": request.headers.get("webhook-timestamp")!,
  "webhook-signature": request.headers.get("webhook-signature")!,
});

Delivery

  • Answer with any 2xx, quickly: an attempt gives up after 20 seconds, or 10 without a response from you. Do the work afterwards.
  • A message not answered 2xx is sent again, half a minute later, then at longer gaps up to an hour apart, for a day: 30 attempts in all. One that can never arrive, such as a URL whose host has no public address, isn't tried again.
  • We post only to https URLs whose host has public addresses, and don't follow redirects.

On this page