Seal Docs

Webhooks API

Configure webhook endpoints for real-time event notifications

Webhooks API

The Webhooks API allows you to configure HTTP endpoints that receive real-time notifications when events occur in your Seal account. Webhooks enable you to build reactive integrations that respond immediately to document lifecycle events.

The Webhook Object

Attributes

AttributeTypeDescription
idstringUnique webhook identifier
namestringHuman-readable label for this endpoint
urlstringHTTPS endpoint URL
eventsarrayArray of subscribed event types
statusstringStatus: active, paused, disabled
secret_prefixstringFirst 12 characters of the HMAC secret (full secret shown once at creation)
descriptionstringOptional description
statsobjectDelivery stats: total_deliveries, successful, failed, success_rate
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last update timestamp

Example Object

{
  "id": "wh_abc123",
  "name": "Production webhook",
  "url": "https://api.example.com/webhooks/seal",
  "events": ["document.sent", "recipient.signed", "document.completed"],
  "status": "active",
  "secret_prefix": "whsec_ac7Ng4",
  "description": "Notifies our CRM on document events",
  "stats": {
    "total_deliveries": 42,
    "successful": 41,
    "failed": 1,
    "success_rate": 97
  },
  "created_at": "2024-01-15T10:00:00Z",
  "updated_at": "2024-01-27T11:00:00Z"
}

Security: The full HMAC secret (whsec_...) is only returned once, at creation time. Subsequent reads show only secret_prefix (the first 12 characters) for identification. Store the secret securely — if lost, use the rotate-secret endpoint to generate a new one.

List Webhooks

Retrieve all webhook endpoints for your organization.

Endpoint

GET /api/v1/webhooks

Required Scope

seal:webhooks:manage

TypeScript Example

const response = await fetch("https://seal.convex.site/api/v1/webhooks", {
  headers: {
    Authorization: "Bearer ak_your_api_key_here",
  },
});

const webhooks = await response.json();

cURL Example

curl -X GET https://seal.convex.site/api/v1/webhooks \
  -H "Authorization: Bearer ak_your_api_key_here"

Get Webhook

Retrieve a single webhook by ID.

Endpoint

GET /api/v1/webhooks/get?id={id}

Required Scope

seal:webhooks:manage

TypeScript Example

const response = await fetch("https://seal.convex.site/api/v1/webhooks/get?id=wh_abc123", {
  headers: {
    Authorization: "Bearer ak_your_api_key_here",
  },
});

const webhook = await response.json();

Create Webhook

Create a new webhook endpoint.

Endpoint

POST /api/v1/webhooks

Required Scope

seal:webhooks:manage

Request Body

FieldTypeRequiredDescription
namestringYesWebhook name
urlstringYesHTTPS endpoint URL
eventsarrayYesArray of event types to subscribe to
descriptionstringNoWebhook description

TypeScript Example

const response = await fetch("https://seal.convex.site/api/v1/webhooks", {
  method: "POST",
  headers: {
    Authorization: "Bearer ak_your_api_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://api.example.com/webhooks/seal",
    events: ["document.sent", "recipient.signed", "document.completed"],
    description: "Production webhook endpoint",
  }),
});

const webhook = await response.json();

cURL Example

curl -X POST https://seal.convex.site/api/v1/webhooks \
  -H "Authorization: Bearer ak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/webhooks/seal",
    "events": ["document.sent", "recipient.signed", "document.completed"]
  }'

Response

{
  "id": "wh_abc123",
  "url": "https://api.example.com/webhooks/seal",
  "events": ["document.sent", "recipient.signed", "document.completed"],
  "status": "active",
  "secret": "whsec_abc123xyz",
  "created_at": "2024-01-27T15:00:00Z"
}

Important: Save the secret value securely. It's only shown once during creation and is required for verifying webhook signatures.

Update Webhook

Update a webhook's configuration.

Endpoint

PUT /api/v1/webhooks/update?id={id}

Required Scope

seal:webhooks:manage

Request Body

FieldTypeDescription
urlstringNew endpoint URL
eventsarrayNew event subscriptions
statusstringNew status: active, paused

TypeScript Example

const response = await fetch("https://seal.convex.site/api/v1/webhooks/update?id=wh_abc123", {
  method: "PUT",
  headers: {
    Authorization: "Bearer ak_your_api_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    events: ["document.sent", "document.completed", "recipient.signed"],
    status: "active",
  }),
});

Delete Webhook

Permanently delete a webhook endpoint.

Endpoint

DELETE /api/v1/webhooks/delete?id={id}

Required Scope

seal:webhooks:manage

TypeScript Example

const response = await fetch("https://seal.convex.site/api/v1/webhooks/delete?id=wh_abc123", {
  method: "DELETE",
  headers: {
    Authorization: "Bearer ak_your_api_key_here",
  },
});

const result = await response.json();
// Returns { "deleted": true } with 200 status

Rotate Secret

Generate a new webhook secret for signature verification.

Endpoint

POST /api/v1/webhooks/rotate-secret?id={id}

Required Scope

seal:webhooks:manage

TypeScript Example

const response = await fetch(
  "https://seal.convex.site/api/v1/webhooks/rotate-secret?id=wh_abc123",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer ak_your_api_key_here",
    },
  },
);

const { secret } = await response.json();

Response

{
  "id": "wh_abc123",
  "secret": "whsec_new_secret_xyz",
  "rotated_at": "2024-01-27T16:00:00Z"
}

Best Practice: Rotate webhook secrets periodically (every 90 days) and immediately if you suspect compromise.

Get Event Types

Retrieve all available webhook event types.

Endpoint

GET /api/v1/webhooks/event-types

Required Scope

seal:webhooks:manage

Available Event Types

See the Webhooks Guide for the complete list of 17 event types and their payloads.

Document Events

  • document.created
  • document.sent
  • document.viewed
  • document.completed
  • document.voided
  • document.expired
  • document.declined

Recipient Events

  • recipient.added
  • recipient.viewed
  • recipient.signed
  • recipient.approved
  • recipient.declined
  • recipient.reminded

Template Events

  • template.created
  • template.updated
  • template.used

Subscribe to All Events

Pass an empty array to receive every event type:

{
  "events": []
}

Next Steps

Last updated on

On this page