Events
Polling and webhooks
An envelope changes a handful of times: sent, opened, signed, completed, sealed. A webhook tells you each time, with one request per change. Reading the envelope on a timer mostly returns the same thing, so the API paces it.
Read once to see it
Right after you send, or right after a signer finishes, one read shows the new state at once:
curl -s https://app-staging.signenvoy.com/v1/documents/$DOC -H "Authorization: Bearer $SENV_API_KEY"
That is the right call for a person checking by hand, or for code a webhook has told that something changed.
Get told: webhooks
Add an endpoint under Settings, Developers, Webhooks, or with the API,
and subscribe to the events you act on. Most integrations need
document.completed (everyone signed) and
document.sealed (the signed PDF is ready to download).
curl -s -X POST https://app-staging.signenvoy.com/v1/webhooks \
-H "Authorization: Bearer $SENV_API_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://your-app.example.com/webhooks/signenvoy", "events": ["document.completed", "document.sealed"]}'
The response carries the endpoint's signing secret, once. Verify
X-SignEnvoy-Signature on every delivery
(how), then read the document named
in the event. Deliveries that fail are retried for a day
(events and retries).
On localhost there is no public URL to deliver to. The CLI forwards the same events to a local handler without a tunnel:
senv webhook tail --forward http://localhost:3000/webhooks/signenvoy --secret YOUR_LOCAL_SECRET
Or read them yourself from the event stream.
If you have to poll
Polling works. These are the rules for GET /v1/documents/{id}:
-
Every 30 seconds. While a document can still change
on its own (
sent,partially_signed, orcompletedand not yet sealed), responses carryX-SignEnvoy-Poll-Interval: 30and aLinkto the webhook docs. -
Send the
ETagback. Every read returns anETag. Send it asIf-None-Matchand an unchanged document answers304 Not Modifiedwith no body. -
Or wait for the change.
?wait=30holds the request for up to 30 seconds and answers as soon as the document differs from yourIf-None-Match(or from what it was when the request arrived). At the deadline you get a 304 if nothing changed. A workspace can hold 10 waiting reads at a time. -
The limit. One API key may read one document 10 times
at once, then once every 15 seconds. Past that the answer is 429
polling-too-fastwithRetry-After. Other documents and other keys are not affected. A key that keeps reading one document gets anX-SignEnvoy-Noticeheader suggesting webhooks. -
Reads can be 5 seconds old. A change made through the
API or by a signer is visible to the next read. A change the sealing
job makes can take up to 5 seconds to show; the
Ageheader says how old a read is.
ETAG=$(curl -s -D - -o /dev/null https://app-staging.signenvoy.com/v1/documents/$DOC \
-H "Authorization: Bearer $SENV_API_KEY" | awk 'tolower($1)=="etag:" {print $2}' | tr -d '\r')
curl -s -w '%{http_code}\n' "https://app-staging.signenvoy.com/v1/documents/$DOC?wait=30" \
-H "Authorization: Bearer $SENV_API_KEY" -H "If-None-Match: $ETAG"