> ## Documentation Index
> Fetch the complete documentation index at: https://signatureapi-daf4ee54.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Store Envelope Data on Completion

> Detect envelope completion with webhooks, retrieve captured data, and persist it to your database

After an envelope completes, you may want to store the signing data in your own database or system of record. This guide shows how to detect when an envelope completes using a webhook, retrieve the envelope details (including any captured input from the signer), and persist the data.

## Overview

The flow works in three steps:

1. SignatureAPI sends an `envelope.completed` webhook event to your endpoint.
2. Your server retrieves the full envelope (including captures) using the API.
3. Your server stores the relevant data in your database.

## Step 1: Set Up a Webhook Endpoint

Register a webhook endpoint in the [Dashboard](https://dashboard.signatureapi.com/settings/webhooks) and subscribe to the `envelope.completed` event. See [Set Up Webhooks](/docs/api/guides/how-to/set-up-webhooks) for detailed instructions.

## Step 2: Create an Envelope with Captures

When creating the envelope, use `capture_as` on interactive places to store values entered by the signer. Also use `metadata` to attach your own identifiers for matching the envelope back to your records.

```json theme={null}
// POST https://api.signatureapi.com/v1/envelopes
// X-API-Key: key_test_...
// Content-Type: application/json

{
  "title": "Order Confirmation",
  "metadata": {
    "order_id": "ORD-2026-1234",
    "customer_id": "cust_5678"
  },
  "documents": [
    {
      "url": "https://example.com/documents/order-confirmation.pdf",
      "places": [
        {
          "key": "customer_signature",
          "type": "signature",
          "recipient_key": "customer"
        },
        {
          "key": "reference_number",
          "type": "text_input",
          "recipient_key": "customer",
          "hint": "Your 8-digit reference code",
          "capture_as": "reference"
        }
      ]
    }
  ],
  "recipients": [
    {
      "type": "signer",
      "key": "customer",
      "name": "Emily Davis",
      "email": "emily@example.com"
    }
  ]
}
```

## Step 3: Handle the Webhook Event

When the envelope completes, SignatureAPI sends an `envelope.completed` event to your endpoint:

```json theme={null}
{
  "id": "evt_4p2oouvNvjp1I9ckgqycH2",
  "type": "envelope.completed",
  "timestamp": "2026-03-04T15:00:01.999Z",
  "data": {
    "object_id": "55072f0e-b919-4d69-89cd-e7e56af00530",
    "object_type": "envelope",
    "envelope_id": "55072f0e-b919-4d69-89cd-e7e56af00530",
    "envelope_metadata": {
      "order_id": "ORD-2026-1234",
      "customer_id": "cust_5678"
    }
  }
}
```

The `envelope_metadata` property reflects the metadata you attached when creating the envelope. You can use these values to match the event to your internal records without making an additional API call.

## Step 4: Retrieve the Envelope

If you need data beyond what the webhook event provides (such as captured input from the signer), use the `envelope_id` from the event to fetch the full envelope.

```json theme={null}
// GET https://api.signatureapi.com/v1/envelopes/55072f0e-b919-4d69-89cd-e7e56af00530
// X-API-Key: key_test_...
```

```json theme={null}
// HTTP Status Code 200

{
  "id": "55072f0e-b919-4d69-89cd-e7e56af00530",
  "title": "Order Confirmation",
  "status": "completed",
  "metadata": {
    "order_id": "ORD-2026-1234",
    "customer_id": "cust_5678"
  },
  "captures": {
    "reference": "11223344"
  },
  //...
}
```

The `captures` object contains any values the signer entered in interactive places that had `capture_as` defined.

## Step 5: Store the Data

With the envelope details and captures in hand, persist the data to your database. Here is a conceptual example:

```js theme={null}
app.post("/webhooks/signatureapi", async (req, res) => {
  const event = req.body;

  if (event.type === "envelope.completed") {
    // Fetch the full envelope to get captures
    const envelope = await fetch(
      `https://api.signatureapi.com/v1/envelopes/${event.data.envelope_id}`,
      { headers: { "X-API-Key": process.env.SIGNATUREAPI_KEY } }
    ).then(r => r.json());

    // Store in your database
    await db.signingRecords.create({
      envelope_id: envelope.id,
      order_id: envelope.metadata.order_id,
      customer_id: envelope.metadata.customer_id,
      reference: envelope.captures.reference,
      completed_at: event.timestamp
    });
  }

  res.status(200).send("OK");
});
```

<Note>
  Always [verify the webhook signature](/docs/api/guides/how-to/set-up-webhooks#verify-the-signature) before processing events in production.
</Note>

## Try It

[Try this example in Postman](/docs/api/postman) using your [test API key](/docs/api/test-mode) to create a free, non-binding test envelope. Test envelopes won't send emails, but you can review them in your dashboard.

## Keep Learning

* Learn more about [captures](/docs/api/resources/envelopes/captures) and which place types support them.
* Set up [webhooks](/docs/api/guides/how-to/set-up-webhooks) with signature verification and retry handling.
* Use [topics](/docs/api/resources/envelopes/topics) to route events from specific envelopes to different webhook endpoints.
* [Download signed documents](/docs/api/guides/use-cases/save-signed-documents) after the envelope completes.
