Flow
Copy
Frontend sends → Backend processes → PDF created
↓ ↓ ↓
Signing data 1. Annotate fields Stored
2. Apply signature
Complete Example
Copy
const express = require('express');
const multer = require('multer');
const upload = multer();
app.post('/api/sign', upload.single('document'), async (req, res) => {
try {
const { eventId, auditTrail, documentFields, signerFields } = req.body;
const document = req.file.buffer.toString('base64');
// 1. Fill document fields
const annotated = await fetch('https://api.superdoc.dev/v1/annotate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERDOC_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
document,
fields: [...documentFields, ...signerFields]
})
});
if (!annotated.ok) throw new Error('Annotation failed');
// 2. Apply digital signature
const annotatedBlob = await annotated.blob();
const signed = await fetch('https://api.superdoc.dev/v1/sign', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERDOC_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
document: Buffer.from(await annotatedBlob.arrayBuffer()).toString('base64'),
auditTrail
})
});
if (!signed.ok) throw new Error('Signing failed');
// 3. Save signed PDF
const signedPdf = await signed.blob();
await saveToS3(signedPdf, `signed/${eventId}.pdf`);
// 4. Log for compliance
await db.signatures.create({
eventId,
signerName: signerFields.find(f => f.id === 'signature')?.value,
signedAt: new Date(),
auditTrail: JSON.stringify(auditTrail)
});
res.json({ success: true, documentId: eventId });
} catch (error) {
console.error('Signing failed:', error);
res.status(500).json({ error: 'Failed to sign document' });
}
});
Download/PDF Generation
Handle download requests to generate PDFs on-demand:Copy
app.post('/api/generate-pdf', async (req, res) => {
const { documentSource, fileName } = req.body;
// If documentSource is URL, fetch it
let document;
if (typeof documentSource === 'string' && documentSource.startsWith('http')) {
const docResponse = await fetch(documentSource);
document = Buffer.from(await docResponse.arrayBuffer()).toString('base64');
} else {
document = documentSource; // Already base64 or will be handled
}
// 1. Convert to PDF
const result = await fetch('https://api.superdoc.dev/v1/convert?from=docx&to=pdf', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERDOC_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
document,
})
});
if (!result.ok) throw new Error('PDF generation failed');
// Send PDF back to frontend
const pdf = await result.blob();
res.type('application/pdf');
res.send(Buffer.from(await pdf.arrayBuffer()));
});
Data Structure
The frontend sends this data to your backend:Copy
{
"eventId": "session-123",
"document": "...", // If uploading file
"documentFields": [
{ "id": "employee_name", "value": "Jane Smith" }
],
"signerFields": [
{ "id": "signature", "value": "Jane Smith" },
{ "id": "accept_terms", "value": true }
],
"auditTrail": [
{ "type": "ready", "timestamp": "2024-01-15T10:30:00Z" },
{ "type": "scroll", "timestamp": "2024-01-15T10:30:15Z",
"data": { "percent": 100 } },
{ "type": "field_change", "timestamp": "2024-01-15T10:30:30Z",
"data": { "fieldId": "signature", "value": "Jane Smith" } },
{ "type": "submit", "timestamp": "2024-01-15T10:30:45Z" }
],
"timestamp": "2024-01-15T10:30:45Z",
"duration": 45000,
"isFullyCompleted": true
}
API Reference
- Authentication - Get your API key
- Annotate endpoint - Fill fields
- Sign endpoint - Apply signature