---
title: "envelope.completed delivered to your endpoint"
method: POST
path: "envelope.completed"
tags: ["Webhooks"]
---

# envelope.completed delivered to your endpoint

`POST envelope.completed` (webhook)

InkSeal sends this request to every active subscription whose `events` array contains `envelope.completed`, or whose `events` is `null`. Verify `X-InkSeal-Signature` against the raw body before doing anything else, and deduplicate on `id`.

## Headers

- `X-InkSeal-Event-Id` string, required
- `X-InkSeal-Signature` string, required
- `X-InkSeal-Timestamp` string, required

## Payload

- object
  - `id` string, required: Stable event id, derived from the transition rather than the clock. Every retry of this event carries the same value.
  - `type` 'envelope.completed', required: The event type.
  - `data` WebhookEnvelopeCompletedPayload, required: Every signer has signed and the completed PDF is available.
    - `envelopeId` string, required: Public id of the envelope.
    - `documentName` string, required: The document's original filename.
    - `completedAt` string, date-time, required: When the last signature committed.
    - `pdfHash` string, required: SHA-256 of the completed PDF, matching the X-Document-Hash header on the download.
    - `signers` object[], required: Every signer, with the time each signed.
      - `id` string, required: The signer's public id.
      - `name` string, required: The signer's display name.
      - `email` string, required: The signer's email address.
      - `status` string, required: The signer's current status.
      - `signedAt` string, date-time, nullable, required: When this signer signed, or null.
    - `values` union, required: Named field values included in a completion webhook. If the UTF-8 JSON representation would exceed 32,768 bytes, the map is replaced by the truncation sentinel. Read the fields endpoint for the complete values.
      - NamedFieldValues: Named field values keyed by the stable field name. Unnamed fields are omitted. Values keep their stored string representation; an unfilled field is null.
      - object
        - `_truncated` true, required
  - `timestamp` string, date-time, required: When the transition committed. Not the same as X-InkSeal-Timestamp, which is when this attempt was made.

## Acknowledgement `200`

Acknowledged. Return any 2xx, with or without a body, as soon as the event is stored; do your work afterwards. Anything that is not a 2xx, including a redirect (redirects are never followed) and a response slower than the 30 second timeout, counts as a failure and is retried with exponential backoff from 60 seconds, doubling per attempt and capped at 1 hour, for at most 6 attempts. After the sixth the event is terminal and only a manual retry through POST /webhooks/{webhookId}/events/{eventId}/retry will send it again.

---

[API](https://skmtc.dev/inkseal/apis/inkseal-api.md) · [All operations](https://skmtc.dev/inkseal/apis/inkseal-api/llms.txt) · [OpenAPI document](https://skmtc.dev/inkseal/apis/inkseal-api/revisions/c440c981d578?raw)
