docjet
v1.0.0
Published
Official DocJet JS/TS SDK — fetch-based, zero runtime deps, ESM+CJS, full TypeScript types
Readme
docjet
Official JavaScript/TypeScript SDK for DocJet — the document generation API for AI agents and automation builders.
Send a template ID or raw HTML plus data; receive a branded PDF or PNG in seconds.
Install
npm install docjetRequirements: Node.js 18+ (native fetch required). Zero runtime dependencies.
Quickstart
import { DocJetClient } from 'docjet';
const client = new DocJetClient({ apiKey: 'binfra_your_api_key_here' });
// Render a PDF — returns a signed download URL
const { url } = await client.render({
template_id: 'invoice-ro',
data: {
client: 'Acme SRL',
total: 1500,
currency: 'RON',
},
});
console.log('PDF ready:', url);
// https://api.docjet.dev/v1/outputs/abc123?exp=...&sig=...Render from raw HTML
const { url } = await client.render({
html: '<h1>Hello World</h1><p>Generated by DocJet.</p>',
data: { name: 'World' },
});Render a PNG image
const { url } = await client.renderImage({
template_id: 'og-card',
data: { title: 'My Article', description: 'Summary here' },
width: 1200,
height: 630,
});List available templates
const templates = await client.listTemplates();
// [{ id: 'invoice-ro', name: 'Invoice RO', outputType: 'pdf', ... }, ...]Check API key usage
const usage = await client.usage();
console.log(`Used ${usage.used}/${usage.limit} renders this ${usage.period}`);
// Used 42/1000 renders this 2026-06Webhook Signature Verification
The differentiator most doc APIs skip: verifyWebhookSignature lets you authenticate incoming DocJet webhook callbacks before trusting them.
Every DocJet webhook POST includes an X-DocJet-Signature header. Verify it before processing:
import { verifyWebhookSignature } from 'docjet';
// In your webhook handler (Express, Fastify, Hono, etc.):
app.post('/webhooks/docjet', (req, res) => {
const rawBody = req.body; // raw string BEFORE JSON.parse — critical!
const signature = req.headers['x-docjet-signature'] as string;
const secret = process.env.DOCJET_WEBHOOK_SECRET!;
if (!verifyWebhookSignature(rawBody, signature, secret)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(rawBody);
// event.type === 'render.complete', event.jobId, event.url ...
res.json({ received: true });
});verifyWebhookSignature API
verifyWebhookSignature(
rawBody: string, // Raw request body string (before JSON.parse)
headerValue: string, // X-DocJet-Signature header value
secret: string, // Your per-key webhook signing secret
toleranceSeconds?: number // Replay window in seconds (default: 300)
): booleanSecurity properties:
- HMAC-SHA256 over
${timestamp}.${rawBody}— exact inverse of server signing - Timing-safe comparison (
timingSafeEqual) — no early-exit hex compare leaks - 5-minute replay window — captured signatures expire after 300s (configurable)
Error Handling
import { DocJetClient, DocJetError } from 'docjet';
const client = new DocJetClient({ apiKey: process.env.DOCJET_API_KEY! });
try {
const { url } = await client.render({ template_id: 'invoice-ro', data: {} });
console.log(url);
} catch (err) {
if (err instanceof DocJetError) {
console.error(`DocJet error [${err.code}] HTTP ${err.statusCode}: ${err.message}`);
// err.code: 'AUTH_INVALID' | 'QUOTA_EXCEEDED' | 'RATE_LIMITED' | 'TEMPLATE_NOT_FOUND' | ...
// err.statusCode: 401 | 429 | 404 | 422 | 500 | ...
} else {
throw err; // re-throw unexpected errors
}
}Error codes
| Code | HTTP | Meaning |
|------|------|---------|
| AUTH_INVALID | 401 | API key missing or invalid |
| PAYLOAD_INVALID | 422 | Invalid request body or template data |
| TEMPLATE_NOT_FOUND | 404 | Template ID does not exist |
| RATE_LIMITED | 429 | Per-minute rate limit exceeded |
| QUOTA_EXCEEDED | 429 | Monthly quota exhausted |
| CONCURRENCY_EXCEEDED | 429 | Concurrent render limit reached |
| INTERNAL_ERROR | 500 | Server error |
Configuration
const client = new DocJetClient({
apiKey: 'binfra_...', // required
baseUrl: 'https://api.docjet.dev', // optional, default shown
});Try it free
Use the public demo key (rate-limited to 3 req/min, 50 renders/month):
# cURL
curl -s -X POST https://api.docjet.dev/v1/render?response=url \
-H "Authorization: Bearer binfra_9afb57dbb6478c441ad101129fca65847f5745403f9d718b3de6d934c9b63f88" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Hello DocJet</h1>","data":{}}'// SDK
const client = new DocJetClient({
apiKey: 'binfra_9afb57dbb6478c441ad101129fca65847f5745403f9d718b3de6d934c9b63f88',
});
const { url } = await client.render({ html: '<h1>Hello DocJet</h1>', data: {} });Get a production key at docjet.dev.
License
MIT
