Public Docs

API and Webhooks

Customer-facing integration guide for authenticated API endpoints and outbound webhook delivery.

Documentation Example Language

Applies to all request snippets on this page.

Base URL

Use https://ezdzwaiver.com for all API requests.

Authentication

Send your API key with each request via X-API-Key.

curl -X GET "https://ezdzwaiver.com/api/v1/waivers?page=1&limit=25" \
  -H "X-API-Key: sk_live_..."

Manage keys in Settings -> API Keys.

API Endpoints

GET/api/v1/waivers

List Waivers

Returns waivers for your organization with pagination and optional filters.

  • Query params: page (default 1), limit (default 50, max 100)
  • Optional filters: templateId, startDate, endDate

Request example (cURL)

curl -X GET "https://ezdzwaiver.com/api/v1/waivers?page=1&limit=25&templateId=template_uuid" \
  -H "X-API-Key: sk_live_..."

Response example

{
  "success": true,
  "data": [
    {
      "id": "waiver_uuid",
      "template_id": "template_uuid",
      "signer_name": "Jane Doe",
      "signer_email": "jane@example.com",
      "signer_phone": null,
      "signer_date_of_birth": null,
      "signed_at": "2026-02-11T17:00:00.000Z",
      "pdf_url": "https://...",
      "template_name": "Skydiving Waiver"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 1,
    "totalPages": 1
  }
}
GET/api/v1/waivers/:id

Get Waiver Details

Fetches full details for a single waiver.

  • Returns 404 if the waiver does not exist for your org.

Request example (cURL)

curl -X GET "https://ezdzwaiver.com/api/v1/waivers/waiver_uuid" \
  -H "X-API-Key: sk_live_..."

Response example

{
  "success": true,
  "data": {
    "id": "waiver_uuid",
    "org_id": "org_uuid",
    "template_id": "template_uuid",
    "signer_name": "Jane Doe",
    "signer_email": "jane@example.com",
    "signed_at": "2026-02-11T17:00:00.000Z",
    "form_data": {
      "booking_id": "BK-1234"
    },
    "pdf_url": "https://...",
    "template_name": "Skydiving Waiver",
    "template_category": "skydiving"
  }
}
GET/api/v1/waivers/:id/events

Get Waiver Events

Fetches audit trail events for a specific waiver, including field completions, updates, views, and downloads.

  • Returns events sorted by timestamp (most recent first)
  • Timestamps include seconds and milliseconds for precise tracking
  • Event actions: field_completed, field_updated, viewed_after_signing, pdf_downloaded_by_signer, pdf_downloaded_by_admin

Request example (cURL)

curl -X GET "https://ezdzwaiver.com/api/v1/waivers/waiver_uuid/events" \
  -H "X-API-Key: sk_live_..."

Response example

{
  "success": true,
  "data": {
    "events": [
      {
        "id": "event_uuid",
        "event_type": "downloaded",
        "event_data": {
          "action": "pdf_downloaded_by_signer"
        },
        "trigger_source": "public_signing_page",
        "ip_address": "192.168.1.1",
        "created_at": "2026-02-11T22:16:51.660Z"
      },
      {
        "id": "event_uuid",
        "event_type": "viewed",
        "event_data": {
          "action": "field_updated",
          "field_id": "field_uuid",
          "field_label": "Full Name"
        },
        "trigger_source": "public_signing_page",
        "ip_address": "192.168.1.1",
        "created_at": "2026-02-11T22:09:22.561Z"
      }
    ]
  }
}
GET/api/v1/templates

List Templates

Returns active templates available to your organization.

  • Optional query params: category, isPublic=true|false

Request example (cURL)

curl -X GET "https://ezdzwaiver.com/api/v1/templates?category=skydiving&isPublic=false" \
  -H "X-API-Key: sk_live_..."

Response example

{
  "success": true,
  "data": [
    {
      "id": "template_uuid",
      "name": "Skydiving Waiver",
      "description": "Primary tandem waiver",
      "category": "skydiving",
      "version": 3,
      "is_public": false,
      "fields": [],
      "styling": {},
      "created_at": "2026-02-01T15:00:00.000Z",
      "updated_at": "2026-02-10T11:30:00.000Z"
    }
  ]
}

Webhooks

Configure webhook endpoints in Settings -> Webhooks. EZ DZ sends real-time events to your server via HTTP POST requests.

🔐 Security Requirements

  • Signing secrets are auto-generated and required for all webhooks
  • Secret is shown only once when you create the webhook - save it immediately!
  • Format: whsec_abc123...
  • You must verify signatures to ensure requests are from EZ DZ
  • To rotate a secret: delete and recreate the webhook

Delivery behavior

  • Method: POST (JSON)
  • Timeout: 10 seconds
  • Success condition: any 2xx response
  • Retry delays: 1s, 5s, 25s, 125s, 625s
  • Maximum attempts: 5

Request headers

  • X-Webhook-Event
  • X-Webhook-Delivery
  • X-Webhook-Timestamp
  • X-Webhook-Signature (when secret is set)

Event names

waiver.signedwaiver.viewedwaiver.voidedcertificate.generatedwaiver.validity.expiringwaiver.validity.expiredwaiver.validity.renewedwaiver.profile.linked

Webhook payload example

{
  "event": "waiver.signed",
  "data": {
    "waiver_id": "waiver_uuid",
    "template_id": "template_uuid",
    "signer_name": "Jane Doe",
    "signed_at": "2026-02-11T17:00:00.000Z",
    "pdf_url": "https://..."
  },
  "timestamp": "2026-02-11T17:00:00.000Z",
  "org_id": "org_uuid"
}

Signature verification (cURL) - REQUIRED

Every webhook includes an X-Webhook-Signature header with an HMAC SHA-256 signature. You must verify this signature using your webhook's secret to ensure the request is authentic.

# Signature verification happens in your receiving server.
# cURL is generally used to test webhook payloads, not verify signatures.
# Use one of the server-side examples (Node/Python) below in your app.

Implementation checklist:

  • Use the raw request body (before JSON parsing)
  • Use crypto.timingSafeEqual() or hmac.compare_digest() to prevent timing attacks
  • Check X-Webhook-Timestamp and reject old requests (e.g., >5 minutes)
  • Store X-Webhook-Delivery ID to prevent duplicate processing
  • Return 200 status quickly - process asynchronously if needed

Errors

Errors use a common response shape.

{
  "success": false,
  "error": "Human-readable message",
  "code": "MACHINE_CODE"
}

AI Context Pack

Copy the complete context from this page and paste it into your coding assistant.

Use this context to build an EZDZ Waiver integration client and webhook receiver.

Preferred request language: cURL

Base URL:
- https://ezdzwaiver.com

Authentication:
- Send API key in X-API-Key header.
- Example request (cURL):
curl -X GET "https://ezdzwaiver.com/api/v1/waivers?page=1&limit=25" \
  -H "X-API-Key: sk_live_..."

Public API endpoints:
GET /api/v1/waivers
Returns waivers for your organization with pagination and optional filters.
- Query params: page (default 1), limit (default 50, max 100)
- Optional filters: templateId, startDate, endDate
Request example (cURL):
curl -X GET "https://ezdzwaiver.com/api/v1/waivers?page=1&limit=25&templateId=template_uuid" \
  -H "X-API-Key: sk_live_..."
Response example:
{
  "success": true,
  "data": [
    {
      "id": "waiver_uuid",
      "template_id": "template_uuid",
      "signer_name": "Jane Doe",
      "signer_email": "jane@example.com",
      "signer_phone": null,
      "signer_date_of_birth": null,
      "signed_at": "2026-02-11T17:00:00.000Z",
      "pdf_url": "https://...",
      "template_name": "Skydiving Waiver"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 1,
    "totalPages": 1
  }
}

---

GET /api/v1/waivers/:id
Fetches full details for a single waiver.
- Returns 404 if the waiver does not exist for your org.
Request example (cURL):
curl -X GET "https://ezdzwaiver.com/api/v1/waivers/waiver_uuid" \
  -H "X-API-Key: sk_live_..."
Response example:
{
  "success": true,
  "data": {
    "id": "waiver_uuid",
    "org_id": "org_uuid",
    "template_id": "template_uuid",
    "signer_name": "Jane Doe",
    "signer_email": "jane@example.com",
    "signed_at": "2026-02-11T17:00:00.000Z",
    "form_data": {
      "booking_id": "BK-1234"
    },
    "pdf_url": "https://...",
    "template_name": "Skydiving Waiver",
    "template_category": "skydiving"
  }
}

---

GET /api/v1/waivers/:id/events
Fetches audit trail events for a specific waiver, including field completions, updates, views, and downloads.
- Returns events sorted by timestamp (most recent first)
- Timestamps include seconds and milliseconds for precise tracking
- Event actions: field_completed, field_updated, viewed_after_signing, pdf_downloaded_by_signer, pdf_downloaded_by_admin
Request example (cURL):
curl -X GET "https://ezdzwaiver.com/api/v1/waivers/waiver_uuid/events" \
  -H "X-API-Key: sk_live_..."
Response example:
{
  "success": true,
  "data": {
    "events": [
      {
        "id": "event_uuid",
        "event_type": "downloaded",
        "event_data": {
          "action": "pdf_downloaded_by_signer"
        },
        "trigger_source": "public_signing_page",
        "ip_address": "192.168.1.1",
        "created_at": "2026-02-11T22:16:51.660Z"
      },
      {
        "id": "event_uuid",
        "event_type": "viewed",
        "event_data": {
          "action": "field_updated",
          "field_id": "field_uuid",
          "field_label": "Full Name"
        },
        "trigger_source": "public_signing_page",
        "ip_address": "192.168.1.1",
        "created_at": "2026-02-11T22:09:22.561Z"
      }
    ]
  }
}

---

GET /api/v1/templates
Returns active templates available to your organization.
- Optional query params: category, isPublic=true|false
Request example (cURL):
curl -X GET "https://ezdzwaiver.com/api/v1/templates?category=skydiving&isPublic=false" \
  -H "X-API-Key: sk_live_..."
Response example:
{
  "success": true,
  "data": [
    {
      "id": "template_uuid",
      "name": "Skydiving Waiver",
      "description": "Primary tandem waiver",
      "category": "skydiving",
      "version": 3,
      "is_public": false,
      "fields": [],
      "styling": {},
      "created_at": "2026-02-01T15:00:00.000Z",
      "updated_at": "2026-02-10T11:30:00.000Z"
    }
  ]
}

---

POST /api/v1/waivers/batch
Generates multiple signing tokens for a template in one request.
- Body fields: templateId, count (1-100), expiresInHours
Request example (cURL):
curl -X POST "https://ezdzwaiver.com/api/v1/waivers/batch" \
  -H "X-API-Key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "template_uuid",
    "count": 3,
    "expiresInHours": 168
  }'
Response example:
{
  "success": true,
  "data": {
    "templateId": "template_uuid",
    "templateName": "Skydiving Waiver",
    "count": 3,
    "expiresAt": "2026-02-18T17:00:00.000Z",
    "tokens": [
      {
        "tokenId": "token_uuid_1",
        "token": "token_value_1",
        "signingUrl": "https://your-app/sign/token_value_1"
      },
      {
        "tokenId": "token_uuid_2",
        "token": "token_value_2",
        "signingUrl": "https://your-app/sign/token_value_2"
      }
    ]
  }
}

---

POST /api/v1/waivers/send
Creates a signing token and queues email delivery to the recipient.
- Body fields: templateId, email, expiresInHours, metadata
- Requires email configuration to be enabled for the account/org
Request example (cURL):
curl -X POST "https://ezdzwaiver.com/api/v1/waivers/send" \
  -H "X-API-Key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "template_uuid",
    "email": "guest@example.com",
    "expiresInHours": 72,
    "metadata": {
      "booking_id": "BK-1234",
      "jump_type": "Tandem"
    }
  }'
Response example:
{
  "success": true,
  "data": {
    "tokenId": "token_uuid",
    "token": "token_value",
    "signingUrl": "https://your-app/sign/token_value",
    "expiresAt": "2026-02-14T17:00:00.000Z",
    "templateName": "Skydiving Waiver",
    "email": "guest@example.com",
    "jobId": "queue_job_id"
  }
}

Webhook delivery behavior:
- EZDZ sends outbound POST requests with JSON payloads.
- Success = any 2xx response.
- Timeout = 10 seconds.
- Retries: 1s, 5s, 25s, 125s, 625s (up to 5 attempts).
- Headers: X-Webhook-Event, X-Webhook-Delivery, X-Webhook-Timestamp.
- X-Webhook-Signature: REQUIRED - HMAC SHA-256 signature (all webhooks have auto-generated secrets).
- Webhook secrets are auto-generated (format: whsec_...) and shown ONLY ONCE at creation.
- You MUST verify signatures to ensure requests are authentic - see signature verification examples.

Webhook event names:
- waiver.signed
- waiver.viewed
- waiver.voided
- certificate.generated
- waiver.validity.expiring
- waiver.validity.expired
- waiver.validity.renewed
- waiver.profile.linked

Webhook payload example:
{
  "event": "waiver.signed",
  "data": {
    "waiver_id": "waiver_uuid",
    "template_id": "template_uuid",
    "signer_name": "Jane Doe",
    "signed_at": "2026-02-11T17:00:00.000Z",
    "pdf_url": "https://..."
  },
  "timestamp": "2026-02-11T17:00:00.000Z",
  "org_id": "org_uuid"
}

Signature verification example (cURL):
# Signature verification happens in your receiving server.
# cURL is generally used to test webhook payloads, not verify signatures.
# Use one of the server-side examples (Node/Python) below in your app.

Error response shape:
{
  "success": false,
  "error": "Human-readable message",
  "code": "MACHINE_CODE"
}

Implementation requirements:
1) Verify signatures using raw request body.
2) Enforce timestamp tolerance (suggest 5 minutes).
3) Make webhook handling idempotent using X-Webhook-Delivery.
4) Return 200 quickly after durable enqueue in your system.
5) Retry transient failures in your own processors.