Webhooks

Webhooks allow you to receive real-time notifications when documents are completed. Instead of polling the API for document status, QuickSign will send HTTP POST requests to your configured webhook URL.

Use Case

Webhooks are ideal for:
  • Real-time updates: Receive instant notifications when documents are signed
  • Workflow automation: Trigger downstream processes automatically
  • Reduced API calls: Eliminate the need for status polling
  • Better UX: Provide immediate feedback to users

Setup Webhook URL

To start receiving webhook notifications, you need to configure a webhook URL in your account:

1

Prepare Your Endpoint

Create an HTTP endpoint in your application that can receive POST requests. This endpoint should:

  • Accept POST requests with JSON payload
  • Respond with HTTP 200-299 status code
  • Process the webhook asynchronously if possible
  • Be publicly accessible (not behind a firewall)
2

Configure Webhook URL

Log in to your QuickSign account and navigate to Settings → API Settings. Enter your webhook URL in the Webhook URL field and save.

Example URLs

  • https://yourdomain.com/api/webhooks/quicksign
  • https://api.yourapp.com/webhooks/documents/completed
3

Test Your Endpoint

Complete a test document to verify your webhook endpoint receives the notification correctly.

Webhook Payload

When a document status changes to COMPLETED, QuickSign will send a POST request to your webhook URL with the following payload:

Request Headers

Webhook Request Headerstext
Content-Type: application/json
User-Agent: QuickSign-API/1.0

Request Body

Webhook Payloadjson
{
  "documentId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "COMPLETED",
  "downloadUrl": "https://s3.amazonaws.com/bucket/path/to/signed-document.pdf"
}

Payload Fields

Webhook Fields

NameTypeRequiredDescription
documentIdstringRequiredUUID of the completed document
statusstringRequiredDocument status (always "COMPLETED" for webhook notifications)
downloadUrlstringRequiredPre-signed S3 URL to download the signed PDF document

Download URL Expiry

The downloadUrl is a pre-signed S3 URL that may expire after a certain time period. Download and store the document immediately upon receiving the webhook.

Example Webhook Handler

Node.js (Express)

Express Webhook Handlerjavascript
const express = require('express');
const app = express();

app.use(express.json());

app.post('/api/webhooks/quicksign', async (req, res) => {
  try {
    const { documentId, status, downloadUrl } = req.body;
    
    console.log(`Document ${documentId} is now ${status}`);
    
    // Download the signed document
    const response = await fetch(downloadUrl);
    const buffer = await response.arrayBuffer();
    
    // Save to your storage
    // await saveDocument(documentId, buffer);
    
    // Update your database
    // await updateDocumentStatus(documentId, status);
    
    // Notify users
    // await sendNotification(documentId);
    
    // Return 200 OK to acknowledge receipt
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Python (Flask)

Flask Webhook Handlerpython
from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/api/webhooks/quicksign', methods=['POST'])
def webhook_handler():
    try:
        data = request.get_json()
        document_id = data.get('documentId')
        status = data.get('status')
        download_url = data.get('downloadUrl')
        
        print(f'Document {document_id} is now {status}')
        
        # Download the signed document
        response = requests.get(download_url)
        pdf_content = response.content
        
        # Save to your storage
        # save_document(document_id, pdf_content)
        
        # Update your database
        # update_document_status(document_id, status)
        
        # Notify users
        # send_notification(document_id)
        
        # Return 200 OK
        return jsonify({'received': True}), 200
    except Exception as e:
        print(f'Webhook error: {e}')
        return jsonify({'error': 'Internal server error'}), 500

if __name__ == '__main__':
    app.run(port=3000)

Security Considerations

Verify Request Origin

To ensure webhook requests are genuinely from QuickSign, check the User-Agent header:

Verify User-Agentjavascript
if (req.headers['user-agent'] !== 'QuickSign-API/1.0') {
  return res.status(403).json({ error: 'Invalid request origin' });
}

Additional Security

The User-Agent can be spoofed. For production use, consider:
  • Implementing webhook signatures (if available)
  • Validating the documentId exists in your system
  • Using IP whitelist for QuickSign servers
  • Implementing rate limiting on your webhook endpoint

HTTPS Required

Your webhook URL must use HTTPS (not HTTP) for security. Self-signed certificates are not supported.

Error Handling

Always respond with an appropriate HTTP status code:

  • 200-299: Success - webhook processed successfully
  • 400-499: Client error - invalid payload or unauthorized
  • 500-599: Server error - temporary failure on your end

Retry Policy

Currently, QuickSign does not retry failed webhook deliveries. If your endpoint is unavailable or returns an error, the webhook will be logged but not retried. Use the audit trail endpoint to check for missed events.

Testing Webhooks

Local Development

For local testing, use a tool like ngrok to expose your local server to the internet:

1

Install ngrok

Install ngrokbash
# macOS
brew install ngrok

# Or download from https://ngrok.com/download
2

Start Your Local Server

Start Serverbash
node server.js  # Listening on port 3000
3

Create Tunnel

Create Tunnelbash
ngrok http 3000

# Output:
# Forwarding: https://abc123.ngrok.io -> localhost:3000
4

Configure Webhook URL

Use the ngrok URL as your webhook URL in QuickSign API Settings:

Ngrok Webhook URLtext
https://abc123.ngrok.io/api/webhooks/quicksign

Online Testing Tools

Use these services to test webhook delivery without writing code:

Troubleshooting

Not Receiving Webhooks?

If you're not receiving webhook notifications, check:

  • ✅ Webhook URL is correctly configured in API Settings
  • ✅ Your endpoint is publicly accessible (not localhost)
  • ✅ Your endpoint responds with HTTP 200-299
  • ✅ You're using HTTPS (not HTTP)
  • ✅ No firewall is blocking incoming requests
  • ✅ Document status actually changed to COMPLETED
  • ✅ Your user account has a webhook URL configured

Webhook Delivery Logs

Currently, webhook delivery logs are not exposed in the API. Contact support if you need assistance troubleshooting webhook delivery issues.

Timeout Issues

Webhook requests have a 10-second timeout. If your endpoint takes longer than 10 seconds to respond, the request will fail. Process webhooks asynchronously:

Async Processingjavascript
app.post('/api/webhooks/quicksign', async (req, res) => {
  // Acknowledge receipt immediately
  res.status(200).json({ received: true });
  
  // Process asynchronously (don't wait for this)
  processWebhookAsync(req.body).catch(console.error);
});

async function processWebhookAsync(data) {
  // Download document
  // Update database
  // Send notifications
  // etc.
}

Best Practices

  • Idempotency: Handle duplicate webhook deliveries gracefully
  • Async Processing: Respond quickly, process slowly
  • Error Logging: Log all webhook errors for debugging
  • Monitoring: Set up alerts for webhook failures
  • Validation: Always validate the payload structure
  • Security: Verify requests and use HTTPS

Webhook Behavior

Webhook Specifications

NameTypeRequiredDescription
Trigger EventinfoOptionalDocument status changes to COMPLETED
Retry PolicyinfoOptionalNo automatic retries
TimeoutinfoOptional10 seconds
MethodinfoOptionalHTTP POST
Content-TypeinfoOptionalapplication/json
User-AgentinfoOptionalQuickSign-API/1.0

Next Steps