Preserve // Developer Platform

Webhooks

Real-time HTTP callbacks when events happen in your organization. Hand this page to your developers. Everything needed to integrate is here.

5 event types JSON over HTTPS

01

How it works

  • Register

    A platform admin saves your endpoint URL in Preserve.

  • Event

    Something happens, like a document being created.

  • Deliver

    Preserve POSTs a JSON payload to every registered webhook.

  • Acknowledge

    Your endpoint returns a 2xx. Done.

02

Setup

Webhooks are managed per organization by a platform admin. Each registration has three fields:

Field Description
name Label included in every delivery so you can tell which registration fired.
description Optional notes for your team.
url Publicly reachable HTTPS endpoint Preserve will POST to. Plain HTTP is not accepted.

03

Delivery

Transport

POST with Content-Type: application/json, sent asynchronously, typically within seconds.

Fan-out

Every registered webhook receives every event. Filter by event name on your side.

Respond fast

Return a 2xx within about 10 seconds; do heavy processing after acknowledging. Slower responses count as failed deliveries. Redirects are not followed.

Retries

Failed deliveries (non-2xx, timeout, or connection error) are retried with increasing backoff for about 4 hours, then dropped.

Delivery is best-effort. An endpoint that stays down past the retry window misses those events permanently, retries can occasionally deliver the same event twice, and a retried event can arrive after a newer one. Make your handler idempotent: deduplicate on the X-Preserve-Delivery header, resolve ordering from payload content rather than arrival order, and treat webhooks as notifications rather than a system of record.

04

Request format

Every delivery uses the same envelope. hook.name identifies your registration; event names which event fired, so you can branch on type; payload carries the event-specific fields documented under Events. The X-Preserve-Delivery header carries a unique ID for the delivery. Retries of the same event reuse the same ID, so deduplicate on it before processing.

{
  "hook": { "name": "<your webhook name>" },
  "event": "<event name>",
  "payload": { … }
}

05

Events

Each event type has its own page with payload fields and example deliveries.

More event types are on our roadmap.

06

Security

Deliveries are not signed yet. Don't trust a request based on its body alone.
  • Use an unguessable URL: a long random token in the path, e.g. /hooks/preserve/3f9a8c…, and reject mismatches.
  • Endpoints must be HTTPS (enforced at registration). Payloads are unsigned, so transport encryption is your only in-transit protection.
  • Treat the payload as a notification. For anything sensitive, look the record up via its id / url.

07

Example receiver

A minimal Node.js / Express endpoint: verify the token, acknowledge immediately, process asynchronously.

Tip: during development, ngrok or a webhook inspection service lets you receive deliveries on a local machine.

const express = require("express");
const app = express();
app.use(express.json());
app.post("/hooks/preserve/:token", (req, res) => {
  if (req.params.token !== process.env.PRESERVE_HOOK_TOKEN) {
    return res.sendStatus(404);
  }
  const { hook, payload } = req.body;
  const deliveryId = req.get("X-Preserve-Delivery");
  res.sendStatus(200); // ack first
  // skip if deliveryId was already processed, then
  // ... enqueue your own processing here ...
});
app.listen(3000);
Preserve Logo

Preserve

Introducing our groundbreaking application designed to serve as an indispensable operational toolbox to technicians in the field.

I am interested in hearing about early adoption licensing rates!

*
*