signelloAPI
Webhooks

Overview

We POST to your URL when something happens to a document, so you never have to poll.

Register an endpoint and Signello sends it a POST whenever one of your documents moves: sent, opened, signed, completed or declined. Each delivery is signed, so you can prove it came from us.

Register an endpoint

Either in the app under Settings → Integrations → API & Webhook, or through the API:

Terminal
curl https://www.signello.se/api/v1/webhook-endpoints \
  -H "Authorization: Bearer sgl_live_yourKeyHere" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourcompany.com/webhooks/signello",
    "events": ["document.signed", "document.completed"],
    "description": "CRM sync"
  }'
Response
{
  "ok": true,
  "data": {
    "id": "c1a7e0d4-2b93-4f61-8a5c-7d20e9b34f18",
    "url": "https://yourcompany.com/webhooks/signello",
    "events": ["document.signed", "document.completed"],
    "enabled": true,
    "description": "CRM sync",
    "secret": "whsec_…",
    "createdAt": "2026-09-03T08:14:22.000Z"
  }
}

The secret appears once

secret is in the create response and in no other response, including a later GET of the same endpoint. Store it before you close the terminal. If you lose it, delete the endpoint and make a new one.

Subscribe to between one and five events per endpoint. A workspace can have up to 10 endpoints, so it is fine to give each consuming system its own with its own secret.

Which URLs we accept

The URL must be a public HTTPS address on port 443. We reject anything that resolves to a private or internal address, with unsafe-url, which rules out localhost, 127.0.0.1, 10.x, 192.168.x, link-local ranges and cloud metadata endpoints. Redirects count as a failed delivery rather than something to follow, because the destination never passed that check.

To develop locally, put a tunnel in front of your machine and register the tunnel's HTTPS URL.

What a delivery looks like

POST /webhooks/signello HTTP/1.1
Content-Type: application/json
User-Agent: Signello-Webhooks/1.0
X-Signello-Event: document.signed
X-Signello-Delivery-Id: 9f4b1c72-0d85-4a39-bc61-5e2f7a84d013
X-Signello-Signature: t=1788432862,v1=5f2c…
HeaderWhat it carries
X-Signello-EventThe event type, same as type in the body.
X-Signello-Delivery-IdUnique per delivery. Use it to make your handler idempotent.
X-Signello-SignatureTimestamp and HMAC. See Verifying deliveries.

Every body has the same outer shape:

{
  "id": "b3c1e07a-5f2d-4c88-a1e9-2f60d4b93c17",
  "type": "document.signed",
  "createdAt": "2026-09-03T08:14:22.000Z",
  "data": { "document": { "…": "…" }, "recipient": { "…": "…" } }
}

Answer fast

Reply 2xx as soon as you have the payload safely stored. We give up on a request after 10 seconds and count it as failed.

If the work you do takes longer than that, put the payload on a queue and answer immediately. A handler that calls three other APIs before replying is the usual reason a healthy integration starts collecting retries.

Retries

Anything that is not a 2xx, plus timeouts, connection errors and redirects, counts as a failure. We retry three times after the first attempt, roughly 5 minutes, 30 minutes and 2 hours later. The sweep runs every 10 minutes, so treat those as floors rather than exact delays: the first retry lands somewhere between 5 and 15 minutes out.

That window is built for the failure that actually happens, which is a deploy or a restart behind the endpoint. After four attempts the delivery is dropped.

Endpoints that stay broken get switched off

After 20 consecutive failures across deliveries we pause the endpoint and show a banner in the app. Fix the URL, then turn it back on in settings or PATCH it with { "enabled": true }, which also clears the failure count. Nothing is replayed, so backfill through GET /documents if you missed something.

Deliver once, handle twice

A retry can arrive after your server already processed the first attempt but failed to answer in time. Treat X-Signello-Delivery-Id as an idempotency key: store the ones you have seen and skip a repeat.

Testing

The Test button on an endpoint in settings sends a ping:

{
  "id": "5a9f2c31-8e04-4d6b-b7c2-1a8e3f5d9042",
  "type": "ping",
  "createdAt": "2026-09-03T08:14:22.000Z",
  "data": { "message": "Signello webhook test" }
}

It is signed like any other delivery, so it is a real end-to-end check of your signature verification. You cannot subscribe to ping; it only ever arrives from that button. Make sure your handler ignores event types it does not know rather than erroring on them.

The most recent deliveries, with their response codes, are listed on the same settings page.

On this page