Datawise Logo

Docs

API Documentation

Version 1.0.0

DataWise Document Exchange

API v1.0.0

Webhooks

E-Signature Document Delivery

Webhooks allow your application to receive signed PDF documents automatically when all signers complete signing. Supports both public and encrypted (private) endpoints.

How It Works

  1. Document sent for signature → E-signature service notifies DDX
  2. DDX processes event → Updates job status
  3. Document completed → DDX downloads signed PDF
  4. PDF delivered → DDX forwards to your webhook URL (if configured)

Flow Diagram

User API Request
    ↓
DDX generates document
    ↓
DDX sends to e-signature service
    ↓
E-Sign Service → Webhook: "Sent" event
    ├→ DDX updates job status: "documentSent"
    └→ DDX charges customer ($0.01 base + $0.10 e-sign)
    ↓
Signer signs document
    ↓
E-Sign Service → Webhook: "Completed" event
    ├→ DDX updates job status: "documentSent & Signed"
    ├→ DDX downloads signed PDF
    └→ DDX forwards to your webhook URL

E-Signature Event Types

Event TypeDescriptionDDX Action
SentDocument successfully sent to signersUpdate job status to documentSent, charge customer
SendFailedFailed to send document to signersUpdate job status to Failed, log error
DeliveryFailedEmail delivery failedLog failure (no job update)
CompletedAll signers have signed the documentDownload PDF, forward to your webhook, update status

Webhook Configuration

For publicly accessible endpoints that don't require authentication:

formData.append('ddxE_webhookUrl', 'https://yourapp.com/api/signed-docs');

Request to your webhook:

POST https://yourapp.com/api/signed-docs
Content-Type: application/pdf

[Binary PDF data]

Encryption Mechanism

Security Features

  • RSA Encryption - Uses 2048-bit RSA public/private key pair
  • One-Time Use - Encryption record deleted immediately after decryption
  • Secure Storage - Encrypted payload stored temporarily in Azure Tables
  • No Credential Exposure - Headers/tokens never logged or exposed

Encryption Payload Structure

interface EncryptedPayload {
  url: string;                    // Required: Webhook URL
  params?: Record<string, any>;   // Optional: Query parameters
  headers?: Record<string, any>;  // Optional: HTTP headers
  responseType?: 'base64';        // Optional: Response format (omit for stream)
  metadata?: Record<string, any>; // Optional: Custom data (only for base64)
}

Get Your Encryption Public Key

Your Encryption Public Key is available in your application's edit section. It's already base64 encoded and ready to copy/paste directly into your code as DDX_PUBLIC_KEY.

Response Formats

Stream (Default)

Best for: Proxying PDFs, large files, memory efficiency

{
  url: 'https://yourapp.com/webhook',
  headers: { 'Authorization': 'Bearer token' }
}

• Content-Type: application/pdf

• Body: Raw binary PDF stream

• Memory: Low (~64KB chunks)

Base64

Best for: JSON APIs, storing in databases, embedding in payloads

{
  url: 'https://yourapp.com/webhook',
  headers: { 'Authorization': 'Bearer token' },
  responseType: 'base64',
  metadata: { orderId: 123, userId: 456 }
}

• Content-Type: application/json

• Body: JSON object with base64-encoded PDF

• Memory: High (~130% of original file size)

JSON Response Structure:

The webhook receives a JSON object containing:

  • • All metadata properties (spread at top level)
  • ddx_file property with base64-encoded PDF
{
  "orderId": 123,
  "userId": 456,
  "ddx_file": "JVBERi0xLjQK..."
}

Handling the Response:

// JavaScript - Access metadata and decode PDF
const { orderId, userId, ddx_file } = req.body;
const pdfBuffer = Buffer.from(ddx_file, 'base64');
fs.writeFileSync(`signed_${orderId}.pdf`, pdfBuffer);

// Python - Access metadata and decode PDF
order_id = request.json['orderId']
user_id = request.json['userId']
pdf_base64 = request.json['ddx_file']
pdf_bytes = base64.b64decode(pdf_base64)
with open(f'signed_{order_id}.pdf', 'wb') as f:
    f.write(pdf_bytes)

Error Handling

Retry Logic

DDX automatically retries webhook deliveries with exponential backoff:

  • • Attempt 1 → Wait 0s
  • • Attempt 2 → Wait 1s
  • • Attempt 3 → Wait 2s

Total retries: 3 attempts over ~3 seconds

Timeout Configuration

  • Download signed document: 30 seconds
  • Delivery to your webhook: 30 seconds
Encryption records are one-time use and deleted after first use. Generate a new encrypted payload for each request. Do not reuse encryption IDs across multiple documents.
Verify you are using the correct DDX public key. Ensure payload structure matches specification. Check for JSON syntax errors before encryption.
Ensure the url field is a valid string URL.
responseType must be base64 or omitted for stream. No other values are accepted.
Ensure your webhook endpoint is accessible, returns HTTP 200 status code, and responds within 30 seconds. Check server logs for errors and verify authentication headers are correct.

Code Examples

Simple Public Webhook

API Request:

const formData = new FormData();
formData.append('ddx_template', templateFile);
formData.append('ddx_outputFormat', 'pdf');
formData.append('ddxE_signers', JSON.stringify([
  {
    signerRole: 'client',
    signerEmail: 'client@example.com',
    signerName: 'John Doe',
    required: ['signature', 'date']
  }
]));
formData.append('ddxE_senderEmail', 'sender@yourcompany.com');
formData.append('ddxE_webhookUrl', 'https://yourapp.com/api/signed-docs');

const response = await fetch('https://api.datawise.app/api/datawise_document_exchange', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
  body: formData
});

Webhook Handler:

app.post('/api/signed-docs', async (req, res) => {
  // req.body is the PDF binary stream
  const pdfBuffer = await streamToBuffer(req);
  fs.writeFileSync('signed-document.pdf', pdfBuffer);

  res.status(200).send('Received');
});

Pro Tip

Use appropriate response format: Stream for proxying PDFs and large files (low memory), Base64 for JSON APIs and database storage. Return HTTP 200 immediately and process PDFs asynchronously for best performance.

© Copyright 2026, Datawise Document Exchange.