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.
Events
The five event types and what each payload contains.
Verifying deliveries
Check the signature before you trust a request. Code for four languages.
Register an endpoint
Either in the app under Settings → Integrations → API & Webhook, or through the API:
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"
}'{
"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…| Header | What it carries |
|---|---|
X-Signello-Event | The event type, same as type in the body. |
X-Signello-Delivery-Id | Unique per delivery. Use it to make your handler idempotent. |
X-Signello-Signature | Timestamp 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.