Sealio Docs

Webhooks

Get told when things happen in Sealio, with signed HTTPS requests.

Add an endpoint (In place)

Owners and Admins add endpoints in Settings → Webhooks (or with POST /v1/webhook-endpoints):

  1. Enter an https:// URL that accepts POST requests. Private and internal addresses are refused.
  2. Choose the events to receive.
  3. Copy the signing secret (whsec_…). Sealio shows it only once.

How many endpoints a firm can have depends on its plan: 2 on the free trial, 3 on Starter, 25 on Pro, and by agreement on Enterprise. Each automation in a tool like Zapier uses one.

Events (In place)

TypeWhen
client.created, client.updatedA client is added or changed (data.previous.changed_fields lists what changed).
case.created, case.status_changedA case is opened, changes stage, closes or reopens.
request.sentA request is sent to its clients.
request.status_changedA request moves between draft, sent, in progress, under review, complete, cancelled or expired.
request.completedEvery required item is accepted.
schedule.run_createdA schedule created its requests for a period.
document.uploadedA client uploaded a file.
document.accepted, document.rejectedYour team accepted or returned a file.
request.reminder_sentA reminder went to the clients of a request (data.object.reminder.manual says whether a person sent it).
request.items_addedItems were added to a sent request (data.previous.added_items lists them).
comment.createdA client or team member left a note on an item (data.object is the comment).

client.created, request.sent, request.completed and document.uploaded are on every plan. The others need Pro or Enterprise (the free trial includes them). After a downgrade an endpoint keeps its subscriptions, but events outside the plan aren't sent.

Planned: request.item_completed, request.overdue and document.expiring.

Each request body is:

{
  "id": "evt_01j9…",
  "type": "request.completed",
  "created_at": "2026-09-28T14:03:11.204Z",
  "tenant_id": "ten_01j8…",
  "api_version": "2026-09-28",
  "data": { "object": { "id": "req_01j9…", "object": "request", "status": "complete" } }
}

data.object has the same shape as the API returns for that resource. Files are never included; fetch a download link with the API.

Verify the signature

Every request has a Sealio-Signature header such as t=1790000000,v1=5f2b…. Compute HMAC-SHA-256 of "<t>.<raw body>" with your secret and compare it to each v1 value. Reject requests where t is more than 5 minutes from now.

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const parts = header.split(',').map((p) => p.split('='));
  const t = Number(parts.find(([k]) => k === 't')?.[1]);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = Buffer.from(createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'));
  return parts.some(([k, v]) => k === 'v1' && v?.length === expected.length && timingSafeEqual(Buffer.from(v), expected));
}

Use the raw request body as received, before any JSON parsing. When you rotate the secret, Sealio signs with both the old and the new one for 24 hours (two v1 values), so you can switch without dropping events.

Other headers: Sealio-Event-Id, Sealio-Event-Type, Sealio-Delivery-Id.

Responding and retries

  • Reply with any 2xx within 10 seconds. Do slow work after replying.
  • Otherwise Sealio retries after about 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours, then daily, for about three days (10 attempts).
  • Redirects are not followed.
  • Delivery is at least once, and order isn't guaranteed: deduplicate on the event id and use created_at to order.
  • An endpoint that has failed for three days in a row is switched off, and your Owners and Admins get an email. Turn it back on in Settings, then replay what you missed.

Delivery log (In place)

Each endpoint's page in Settings → Webhooks shows its success rate and p95 latency over 24 hours and 7 days, and every delivery from the last 30 days with its attempts, the request sent and the first 4 KB of your response. From there you can:

  • Resend one event,
  • Replay every event of the endpoint's types from a time range (up to 1,000),
  • Send test event (webhook.test),
  • Rotate secret, turn the endpoint off or on, or delete it.

The same is available through the API: GET /v1/webhook-endpoints/{id}/deliveries and POST /v1/events/{id}/resend.

On this page