# Code Examples

> Complete code examples for integrating with the WPsigner API in various languages.

edition: pro
Edition: Pro
AI note: This page requires WPsigner Pro. Do not tell Lite users they already have this feature.
HTML: https://docs.wpsigner.com/api/examples/
Markdown: https://docs.wpsigner.com/md/api/examples.md
Source file: api/examples.md

---

This page provides complete, ready-to-use code examples for integrating with the WPsigner API in various programming languages.

## PHP

### Basic API Client

```php
<?php
/**
 * WPsigner API Client for PHP
 */
class WPsignerAPI {
    private $base_url;
    private $api_key;
    private $api_secret;
    
    public function __construct($site_url, $api_key, $api_secret) {
        $this->base_url = rtrim($site_url, '/') . '/wp-json/insigner/v1';
        $this->api_key = $api_key;
        $this->api_secret = $api_secret;
    }
    
    /**
     * Make an API request
     */
    private function request($method, $endpoint, $data = null) {
        $url = $this->base_url . $endpoint;
        
        $headers = [
            'X-WPS-API-Key: ' . $this->api_key,
            'X-WPS-API-Secret: ' . $this->api_secret,
            'Content-Type: application/json'
        ];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
        } elseif ($method === 'PUT') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
        } elseif ($method === 'DELETE') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        }
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        $result = json_decode($response, true);
        
        if ($http_code >= 400) {
            throw new Exception($result['message'] ?? 'API Error', $http_code);
        }
        
        return $result;
    }
    
    /**
     * Get all documents
     */
    public function getDocuments($params = []) {
        $query = http_build_query($params);
        return $this->request('GET', '/documents' . ($query ? '?' . $query : ''));
    }
    
    /**
     * Get a single document
     */
    public function getDocument($id) {
        return $this->request('GET', '/documents/' . $id);
    }
    
    /**
     * Get document signers
     */
    public function getSigners($document_id) {
        return $this->request('GET', '/documents/' . $document_id . '/signers');
    }
    
    /**
     * Add a signer to a document
     */
    public function addSigner($document_id, $name, $email, $role = 'signer', $order = 1) {
        return $this->request('POST', '/documents/' . $document_id . '/signers', [
            'name' => $name,
            'email' => $email,
            'role' => $role,
            'signing_order' => $order
        ]);
    }
    
    /**
     * Send document for signing
     */
    public function sendDocument($document_id) {
        return $this->request('POST', '/documents/' . $document_id . '/send');
    }
    
    /**
     * Get statistics
     */
    public function getStats() {
        return $this->request('GET', '/stats');
    }
}

// Usage Example
$api = new WPsignerAPI(
    'https://your-site.com',
    'wps_your_api_key',
    'your_api_secret'
);

try {
    // List completed documents
    $documents = $api->getDocuments(['status' => 'completed', 'per_page' => 10]);
    
    foreach ($documents as $doc) {
        echo "Document: {$doc['title']} - Status: {$doc['status']}\n";
    }
    
    // Get statistics
    $stats = $api->getStats();
    echo "Total documents: {$stats['total']}, Completed: {$stats['completed']}\n";
    
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

---

## JavaScript / Node.js

### Using Fetch

```javascript
/**
 * WPsigner API Client for JavaScript
 */
class WPsignerAPI {
  constructor(siteUrl, apiKey, apiSecret) {
    this.baseUrl = `${siteUrl.replace(/\/$/, '')}/wp-json/insigner/v1`;
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
  }

  async request(method, endpoint, data = null) {
    const url = `${this.baseUrl}${endpoint}`;
    
    const options = {
      method,
      headers: {
        'X-WPS-API-Key': this.apiKey,
        'X-WPS-API-Secret': this.apiSecret,
        'Content-Type': 'application/json'
      }
    };

    if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
      options.body = JSON.stringify(data);
    }

    const response = await fetch(url, options);
    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.message || 'API Error');
    }

    return result;
  }

  // Documents
  async getDocuments(params = {}) {
    const query = new URLSearchParams(params).toString();
    return this.request('GET', `/documents${query ? '?' + query : ''}`);
  }

  async getDocument(id) {
    return this.request('GET', `/documents/${id}`);
  }

  async deleteDocument(id) {
    return this.request('DELETE', `/documents/${id}`);
  }

  // Signers
  async getSigners(documentId) {
    return this.request('GET', `/documents/${documentId}/signers`);
  }

  async addSigner(documentId, { name, email, role = 'signer', signingOrder = 1 }) {
    return this.request('POST', `/documents/${documentId}/signers`, {
      name,
      email,
      role,
      signing_order: signingOrder
    });
  }

  // Actions
  async sendDocument(documentId) {
    return this.request('POST', `/documents/${documentId}/send`);
  }

  // Statistics
  async getStats() {
    return this.request('GET', '/stats');
  }

  // Audit
  async getAuditTrail(documentId) {
    return this.request('GET', `/documents/${documentId}/audit`);
  }
}

// Usage Example
const api = new WPsignerAPI(
  'https://your-site.com',
  'wps_your_api_key',
  'your_api_secret'
);

(async () => {
  try {
    // Get all pending documents
    const documents = await api.getDocuments({ 
      status: 'sent', 
      per_page: 20 
    });
    
    console.log(`Found ${documents.length} pending documents`);

    // Get details of first document
    if (documents.length > 0) {
      const doc = await api.getDocument(documents[0].id);
      console.log('Document:', doc.title);
      console.log('Signers:', doc.signers.map(s => s.name).join(', '));
    }

    // Get statistics
    const stats = await api.getStats();
    console.log(`Completion rate: ${(stats.completed / stats.total * 100).toFixed(1)}%`);

  } catch (error) {
    console.error('API Error:', error.message);
  }
})();
```

### Using Axios

```javascript
const axios = require('axios');

const api = axios.create({
  baseURL: 'https://your-site.com/wp-json/insigner/v1',
  headers: {
    'X-WPS-API-Key': 'wps_your_api_key',
    'X-WPS-API-Secret': 'your_api_secret'
  }
});

// Get documents
const response = await api.get('/documents', {
  params: { status: 'completed', per_page: 10 }
});

console.log(response.data);
```

---

## Python

```python
"""
WPsigner API Client for Python
"""

from typing import Dict, List, Optional

class WPsignerAPI:
    def __init__(self, site_url: str, api_key: str, api_secret: str):
        self.base_url = f"{site_url.rstrip('/')}/wp-json/insigner/v1"
        self.headers = {
            'X-WPS-API-Key': api_key,
            'X-WPS-API-Secret': api_secret,
            'Content-Type': 'application/json'
        }
    
    def _request(self, method: str, endpoint: str, data: Optional[Dict] = None, params: Optional[Dict] = None):
        url = f"{self.base_url}{endpoint}"
        
        response = requests.request(
            method=method,
            url=url,
            headers=self.headers,
            json=data,
            params=params
        )
        
        if not response.ok:
            error = response.json()
            raise Exception(f"API Error: {error.get('message', 'Unknown error')}")
        
        return response.json()
    
    # Documents
    def get_documents(self, status: Optional[str] = None, page: int = 1, per_page: int = 20) -> List[Dict]:
        params = {'page': page, 'per_page': per_page}
        if status:
            params['status'] = status
        return self._request('GET', '/documents', params=params)
    
    def get_document(self, document_id: int) -> Dict:
        return self._request('GET', f'/documents/{document_id}')
    
    def delete_document(self, document_id: int) -> Dict:
        return self._request('DELETE', f'/documents/{document_id}')
    
    # Signers
    def get_signers(self, document_id: int) -> List[Dict]:
        return self._request('GET', f'/documents/{document_id}/signers')
    
    def add_signer(self, document_id: int, name: str, email: str, 
                   role: str = 'signer', signing_order: int = 1) -> Dict:
        return self._request('POST', f'/documents/{document_id}/signers', {
            'name': name,
            'email': email,
            'role': role,
            'signing_order': signing_order
        })
    
    # Actions
    def send_document(self, document_id: int) -> Dict:
        return self._request('POST', f'/documents/{document_id}/send')
    
    # Statistics
    def get_stats(self) -> Dict:
        return self._request('GET', '/stats')
    
    # Audit
    def get_audit_trail(self, document_id: int) -> Dict:
        return self._request('GET', f'/documents/{document_id}/audit')

# Usage Example
if __name__ == '__main__':
    api = WPsignerAPI(
        site_url='https://your-site.com',
        api_key='wps_your_api_key',
        api_secret='your_api_secret'
    )

    try:
        # Get completed documents
        documents = api.get_documents(status='completed', per_page=10)
        print(f"Found {len(documents)} completed documents")

        for doc in documents:
            print(f"  - {doc['title']} (ID: {doc['id']})")

        # Get statistics
        stats = api.get_stats()
        print(f"\nStatistics:")
        print(f"  Total: {stats['total']}")
        print(f"  Completed: {stats['completed']}")
        print(f"  Pending: {stats['sent'] + stats['viewed']}")

    except Exception as e:
        print(f"Error: {e}")
```

---

## cURL Examples

### List Documents

```bash
curl -X GET "https://your-site.com/wp-json/insigner/v1/documents?status=completed&per_page=10" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

### Get Document Details

```bash
curl -X GET "https://your-site.com/wp-json/insigner/v1/documents/44" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

### Add a Signer

```bash
curl -X POST "https://your-site.com/wp-json/insigner/v1/documents/44/signers" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "role": "signer",
    "signing_order": 1
  }'
```

### Send Document

```bash
curl -X POST "https://your-site.com/wp-json/insigner/v1/documents/44/send" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

### Get Statistics

```bash
curl -X GET "https://your-site.com/wp-json/insigner/v1/stats" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

### Delete Document

```bash
curl -X DELETE "https://your-site.com/wp-json/insigner/v1/documents/44" \
  -H "X-WPS-API-Key: wps_your_key" \
  -H "X-WPS-API-Secret: your_secret"
```

---

## Webhook Handler Examples

### PHP Webhook Handler

```php
<?php
// webhook-handler.php

$secret = 'your_webhook_secret';

// Get the payload and signature
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WPS_SIGNATURE'] ?? '';

// Verify signature
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

// Parse the event
$event = json_decode($payload, true);

// Handle different event types
switch ($event['event']) {
    case 'document.completed':
        $documentId = $event['data']['document_id'];
        $title = $event['data']['document_title'];
        
        // Send notification, update database, etc.
        mail('admin@example.com', 'Document Completed', "Document '{$title}' has been signed.");
        break;
        
    case 'document.declined':
        $reason = $event['data']['decline_reason'];
        // Handle declined document
        break;
        
    default:
        // Log unhandled events
        error_log('Unhandled webhook event: ' . $event['event']);
}

// Respond with success
http_response_code(200);
echo 'OK';
```

### Node.js Webhook Handler

```javascript
const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

const WEBHOOK_SECRET = 'your_webhook_secret';

function verifySignature(payload, signature) {
  const expected = 'sha256=' + 
    crypto.createHmac('sha256', WEBHOOK_SECRET)
          .update(JSON.stringify(payload))
          .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature || '')
  );
}

app.post('/webhooks/wpsigner', (req, res) => {
  const signature = req.headers['x-wps-signature'];
  
  if (!verifySignature(req.body, signature)) {
    return res.status(401).send('Invalid signature');
  }
  
  const { event, data } = req.body;
  
  console.log(`Received event: ${event}`);
  
  switch (event) {
    case 'document.completed':
      console.log(`Document ${data.document_id} completed!`);
      // Process completed document
      break;
      
    case 'document.declined':
      console.log(`Document ${data.document_id} declined: ${data.decline_reason}`);
      // Handle declined document
      break;
      
    default:
      console.log(`Unhandled event: ${event}`);
  }
  
  res.status(200).send('OK');
});

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