Doc-Crafter API allows you to generate thousands of personalized documents from DOCX templates and CSV/Excel data files. This guide will walk you through the complete process.
https://doc-crafter.medevtech.net
{name}, {email})Navigate to the Admin Dashboard at: https://doc-crafter.medevtech.net/admin
Login with your admin credentials. If you don't have an account, contact your system administrator.
Go to the "API Keys" section in the sidebar menu.
Click "Create New API Key" and fill in the required information:
Store your API key securely. You'll use it in the
X-API-Key header for all API requests.
| Field | Type | Required | Description |
|---|---|---|---|
template |
File (DOCX) | ✅ Yes | DOCX template with placeholders like {field_name} |
data |
File (CSV/Excel) | ✅ Yes | CSV or Excel file with data rows |
output_format |
String | ❌ No | "docx" (default) or "pdf" |
| Header | Value | Required |
|---|---|---|
X-API-Key |
Your API key | ✅ Yes |
Content-Type |
multipart/form-data |
✅ Yes |
Content-Type: application/pdf or application/vnd.openxmlformats-officedocument.wordprocessingml.documentContent-Disposition: attachment; filename="generated_{timestamp}.{format}"| Status Code | Error | Description |
|---|---|---|
| 400 | Bad Request | Invalid files or format |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Insufficient permissions or expired key |
| 413 | Payload Too Large | File size exceeds limit (25MB template, 50MB data) |
| 500 | Internal Server Error | Server error during processing |
curl -X POST https://doc-crafter.medevtech.net/generator \
-H "X-API-Key: your-api-key-here" \
-F "template=@invoice_template.docx" \
-F "data=@clients.csv" \
-F "output_format=pdf" \
--output invoices.pdf
# For DOCX output (default):
curl -X POST https://doc-crafter.medevtech.net/generator \
-H "X-API-Key: your-api-key-here" \
-F "template=@template.docx" \
-F "data=@data.csv" \
--output documents.docx
your-api-key-here with
your actual API key. Make sure the file paths are correct relative to
your current directory.
const fs = require('fs');
const FormData = require('form-data');
const https = require('https');
// Create form data
const form = new FormData();
form.append('template', fs.createReadStream('./template.docx'));
form.append('data', fs.createReadStream('./data.csv'));
form.append('output_format', 'pdf');
// Make request
const options = {
hostname: 'doc-crafter.medevtech.net',
path: '/generator',
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
...form.getHeaders()
}
};
const req = https.request(options, (res) => {
if (res.statusCode !== 200) {
console.error('Error:', res.statusCode);
res.pipe(process.stderr);
return;
}
// Save the file
const fileStream = fs.createWriteStream('./output.pdf');
res.pipe(fileStream);
fileStream.on('finish', () => {
console.log('✅ File saved successfully!');
});
});
req.on('error', (error) => {
console.error('Request error:', error);
});
form.pipe(req);
npm install form-data
const express = require('express');
const multer = require('multer');
const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');
const app = express();
const upload = multer({ dest: 'uploads/' });
// Endpoint to handle file upload and forward to Doc-Crafter
app.post('/generate-document', upload.fields([
{ name: 'template', maxCount: 1 },
{ name: 'data', maxCount: 1 }
]), async (req, res) => {
try {
const { output_format = 'docx' } = req.body;
const templateFile = req.files.template[0];
const dataFile = req.files.data[0];
// Create form data
const formData = new FormData();
formData.append('template', fs.createReadStream(templateFile.path), {
filename: templateFile.originalname,
contentType: templateFile.mimetype
});
formData.append('data', fs.createReadStream(dataFile.path), {
filename: dataFile.originalname,
contentType: dataFile.mimetype
});
formData.append('output_format', output_format);
// Forward to Doc-Crafter API
const response = await axios.post(
'https://doc-crafter.medevtech.net/generator',
formData,
{
headers: {
'X-API-Key': process.env.DOC_CRAFTER_API_KEY, // Store in .env
...formData.getHeaders()
},
responseType: 'stream'
}
);
// Set response headers
res.setHeader('Content-Type', response.headers['content-type']);
res.setHeader('Content-Disposition', response.headers['content-disposition']);
// Pipe the response to client
response.data.pipe(res);
// Cleanup uploaded files
fs.unlinkSync(templateFile.path);
fs.unlinkSync(dataFile.path);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
res.status(error.response?.status || 500).json({
error: error.response?.data?.message || 'Generation failed'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
npm install express multer form-data axios
.env file:
DOC_CRAFTER_API_KEY=your-api-key-here
import React, { useState } from 'react';
import axios from 'axios';
function DocumentGenerator() {
const [templateFile, setTemplateFile] = useState(null);
const [dataFile, setDataFile] = useState(null);
const [outputFormat, setOutputFormat] = useState('docx');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
// Store API key (in production, use environment variable or secure storage)
const API_KEY = 'your-api-key-here';
const handleGenerate = async () => {
if (!templateFile || !dataFile) {
setError('Please select both template and data files');
return;
}
setLoading(true);
setError(null);
setSuccess(false);
try {
const formData = new FormData();
formData.append('template', templateFile);
formData.append('data', dataFile);
formData.append('output_format', outputFormat);
const response = await axios.post(
'https://doc-crafter.medevtech.net/generator',
formData,
{
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'multipart/form-data'
},
responseType: 'blob' // Important for binary files
}
);
// Create download link
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
// Get filename from Content-Disposition header
const contentDisposition = response.headers['content-disposition'];
const filename = contentDisposition
? contentDisposition.split('filename=')[1]?.replace(/"/g, '')
: `generated.${outputFormat}`;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
setSuccess(true);
} catch (err) {
// Handle error response
if (err.response) {
if (err.response.status === 401) {
setError('Invalid API key. Please check your API key.');
} else if (err.response.status === 403) {
setError('Access denied. Your API key may be expired or inactive.');
} else if (err.response.status === 413) {
setError('File size too large. Please use smaller files.');
} else {
// Try to parse error message
const reader = new FileReader();
reader.onload = () => {
try {
const errorData = JSON.parse(reader.result);
setError(errorData.message || 'Generation failed');
} catch {
setError('Generation failed. Please try again.');
}
};
reader.readAsText(err.response.data);
}
} else {
setError('Network error. Please check your connection.');
}
} finally {
setLoading(false);
}
};
return (
<div className="document-generator">
<h2>Generate Documents</h2>
<div>
<label>Template File (DOCX):</label>
<input
type="file"
accept=".docx"
onChange={(e) => setTemplateFile(e.target.files[0])}
/>
</div>
<div>
<label>Data File (CSV/Excel):</label>
<input
type="file"
accept=".csv,.xlsx,.xls"
onChange={(e) => setDataFile(e.target.files[0])}
/>
</div>
<div>
<label>Output Format:</label>
<select value={outputFormat} onChange={(e) => setOutputFormat(e.target.value)}>
<option value="docx">DOCX</option>
<option value="pdf">PDF</option>
</select>
</div>
<button onClick={handleGenerate} disabled={loading}>
{loading ? 'Generating...' : 'Generate Document'}
</button>
{error && <div className="error">{error}</div>}
{success && <div className="success">Document generated successfully!</div>}
</div>
);
}
export default DocumentGenerator;
npm install axios
import requests
import os
# API Configuration
API_URL = 'https://doc-crafter.medevtech.net/generator'
API_KEY = 'your-api-key-here' # Store in environment variable
def generate_document(template_path, data_path, output_format='docx', output_path=None):
"""
Generate document from template and data files.
Args:
template_path: Path to DOCX template file
data_path: Path to CSV/Excel data file
output_format: 'docx' or 'pdf'
output_path: Path to save output file (optional)
Returns:
bytes: Generated document as bytes
"""
try:
# Prepare files
with open(template_path, 'rb') as template_file, \
open(data_path, 'rb') as data_file:
files = {
'template': (os.path.basename(template_path), template_file, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'),
'data': (os.path.basename(data_path), data_file, 'application/vnd.ms-excel')
}
data = {
'output_format': output_format
}
headers = {
'X-API-Key': API_KEY
}
# Make request
response = requests.post(
API_URL,
files=files,
data=data,
headers=headers,
timeout=300 # 5 minutes timeout for large files
)
# Check for errors
if response.status_code != 200:
error_msg = 'Unknown error'
try:
error_data = response.json()
error_msg = error_data.get('message', error_data.get('error', 'Unknown error'))
except:
error_msg = response.text or f'HTTP {response.status_code}'
raise Exception(f'Generation failed: {error_msg}')
# Save file if output_path provided
if output_path:
with open(output_path, 'wb') as f:
f.write(response.content)
print(f'✅ Document saved to {output_path}')
return response.content
except requests.exceptions.RequestException as e:
print(f'❌ Request error: {e}')
raise
except Exception as e:
print(f'❌ Error: {e}')
raise
# Example usage
if __name__ == '__main__':
# Generate PDF
generate_document(
template_path='invoice_template.docx',
data_path='clients.csv',
output_format='pdf',
output_path='invoices.pdf'
)
# Generate DOCX
generate_document(
template_path='certificate_template.docx',
data_path='students.xlsx',
output_format='docx',
output_path='certificates.docx'
)
pip install requests
export DOC_CRAFTER_API_KEY="your-api-key-here"
Then use: API_KEY = os.getenv('DOC_CRAFTER_API_KEY')
<?php
$apiUrl = 'https://doc-crafter.medevtech.net/generator';
$apiKey = 'your-api-key-here'; // Store in config file
function generateDocument($templatePath, $dataPath, $outputFormat = 'docx', $outputPath = null) {
global $apiUrl, $apiKey;
// Create CURLFile objects
$templateFile = new CURLFile($templatePath, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', basename($templatePath));
$dataFile = new CURLFile($dataPath, 'text/csv', basename($dataPath));
// Prepare POST data
$postData = [
'template' => $templateFile,
'data' => $dataFile,
'output_format' => $outputFormat
];
// Initialize cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $apiUrl,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $apiKey
],
CURLOPT_TIMEOUT => 300, // 5 minutes
CURLOPT_FOLLOWLOCATION => true
]);
// Execute request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
// Handle errors
if ($error) {
throw new Exception("cURL Error: " . $error);
}
if ($httpCode !== 200) {
$errorData = json_decode($response, true);
$errorMsg = $errorData['message'] ?? $errorData['error'] ?? "HTTP $httpCode";
throw new Exception("Generation failed: $errorMsg");
}
// Save file if output path provided
if ($outputPath) {
file_put_contents($outputPath, $response);
echo "✅ Document saved to $outputPath\n";
}
return $response;
}
// Example usage
try {
// Generate PDF
generateDocument(
'invoice_template.docx',
'clients.csv',
'pdf',
'invoices.pdf'
);
// Generate DOCX
generateDocument(
'certificate_template.docx',
'students.xlsx',
'docx',
'certificates.docx'
);
} catch (Exception $e) {
echo "❌ Error: " . $e->getMessage() . "\n";
}
?>
allow_url_fopen is enabled in your PHP configuration,
or use cURL extension (recommended).
Your DOCX template should contain placeholders wrapped in curly braces that match your data column names.
Invoice #INV-{invoice_number}
Client Information:
Name: {client_name}
Email: {client_email}
Phone: {client_phone}
Invoice Details:
Amount: {amount}
Date: {date}
Due Date: {due_date}
Thank you for your business!
client_name,client_email,client_phone,invoice_number,amount,date,due_date
John Smith,john@example.com,+1234567890,INV-001,$1000,2025-01-01,2025-01-15
Jane Doe,jane@example.com,+0987654321,INV-002,$2500,2025-01-02,2025-01-16
Bob Johnson,bob@example.com,+1122334455,INV-003,$500,2025-01-03,2025-01-17
Client Name → client_nameColumn names are automatically normalized to match template placeholders:
"Client Name" → client_nameCause: Missing or invalid API key
Solution:
X-API-Key header is includedCause: Insufficient permissions or expired key
Solution:
create_document_generation permissionCommon Causes:
output_format value (must be "docx" or "pdf")Cause: File size exceeds limits
Limits:
Solution: Reduce file size or split data into multiple requests
Cause: Server-side error during processing
Solution:
{
"code": 401,
"error": "Unauthorized",
"message": "Missing X-API-Key header"
}
Here's a complete example showing the entire flow from getting an API key to generating a document:
Login to Admin Dashboard → API Keys → Create New → Copy key
INVOICE
Invoice Number: {invoice_number}
Date: {date}
Bill To:
{client_name}
{client_address}
Items:
{items}
Total: {total_amount}
Thank you!
invoice_number,date,client_name,client_address,items,total_amount
INV-001,2025-01-15,John Smith,123 Main St,Product A - $100,100.00
INV-002,2025-01-16,Jane Doe,456 Oak Ave,Product B - $200,200.00
const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');
async function generateInvoices() {
const formData = new FormData();
formData.append('template', fs.createReadStream('invoice_template.docx'));
formData.append('data', fs.createReadStream('invoices.csv'));
formData.append('output_format', 'pdf');
try {
const response = await axios.post(
'https://doc-crafter.medevtech.net/generator',
formData,
{
headers: {
'X-API-Key': process.env.API_KEY,
...formData.getHeaders()
},
responseType: 'stream'
}
);
// Save the file
const writer = fs.createWriteStream('invoices.pdf');
response.data.pipe(writer);
writer.on('finish', () => {
console.log('✅ Invoices generated successfully!');
});
} catch (error) {
console.error('❌ Error:', error.response?.data || error.message);
}
}
generateInvoices();
You'll receive a PDF file with 2 pages, one invoice per client, ready to download or send.
/docs endpoint
Default rate limit: 1000 requests per minute per API key. Contact support for higher limits.