API integration for accounting firms
Learn how your accounting firm integrates LegalDock's API and starts generating legal documents programmatically. A guide with curl and TypeScript.
Karoline, Dokumentkonsulent
Modern accounting firms are digitalising more and more. Clients expect fast answers, and internal systems, from bookkeeping software to client portals, need to fit together better. Legal documents are the next link in the digital chain.
LegalDock's API lets accounting firms generate, fill in and send legal documents programmatically, directly from your own system. No manual copying, no outdated Word templates and no printed signatures.
This guide shows you how to integrate the LegalDock API.
What can the LegalDock API do?
LegalDock's REST API gives access to:
| Function | Description |
|---|---|
| Document generation | Fill a template with fields and receive a finished PDF |
| Digital signature | Send the document for signature via MitID |
| Webhooks | Receive events when the document is signed, rejected or expires |
| Template list | Retrieve all available templates and field descriptions |
| Document archive | Retrieve, download and manage created documents |
All calls go over HTTPS. Authentication uses API keys (a Bearer token). Rate limits depend on your plan.
Prerequisites
Before you begin:
- A LegalDock Partner account with API access
- An API key, retrieved under Settings, API, Generate key
- An HTTP client,
curlfor testing and Node.js 18+ for the TypeScript examples
Step 1: verify the connection
curl https://api.legaldock.org/v1/ping \
-H "Authorization: Bearer YOUR_API_KEY"
Expected response:
{ "status": "ok", "version": "1.0" }
A 401 Unauthorized error means the API key is invalid or expired. Generate a new one under Settings.
Step 2: retrieve available templates
curl https://api.legaldock.org/v1/templates \
-H "Authorization: Bearer YOUR_API_KEY"
{
"templates": [
{ "id": "ansaettelseskontrakt", "name": "Ansaettelseskontrakt" },
{ "id": "nda-standard", "name": "NDA Fortrolighedsaftale" },
{ "id": "lejekontrakt-erhverv", "name": "Erhvervslejekontrakt" },
{ "id": "aktionaeroverenskomst", "name": "Aktionaeroverenskomst" },
{ "id": "konsulentaftale", "name": "Konsulentaftale" }
]
}
Inspect a template to see the field list:
curl https://api.legaldock.org/v1/templates/nda-standard \
-H "Authorization: Bearer YOUR_API_KEY"
Step 3: generate a document
curl -X POST https://api.legaldock.org/v1/documents \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "nda-standard",
"fields": {
"part1Navn": "TechStart ApS",
"part2Navn": "Udvikler A/S",
"formaal": "Droeftelse af muligt teknologisamarbejde",
"varighed": "2 aar",
"dato": "2026-06-01"
},
"meta": {
"reference": "klient-456-nda-2026"
}
}'
Response:
{
"documentId": "doc_xyz789",
"status": "draft",
"downloadUrl": "https://api.legaldock.org/v1/documents/doc_xyz789/pdf",
"previewUrl": "https://app.legaldock.org/preview/doc_xyz789"
}
Tip: Use meta.reference to store your internal client or case number. It lets you find the document from your own system and link the API response to the right client file.
Step 4: request a digital signature
curl -X POST https://api.legaldock.org/v1/documents/doc_xyz789/sign \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"signers": [
{ "name": "Klaus Jensen", "email": "kj@techstart.dk", "role": "party1" },
{ "name": "Sara Holm", "email": "sh@udvikler-as.dk", "role": "party2" }
],
"deadline": "2026-06-15",
"notifyOnSigned": "webhook",
"webhookUrl": "https://your-system.dk/webhooks/legaldock"
}'
LegalDock sends an email to both parties with a signing link. Both sign via MitID on desktop or mobile.
TypeScript integration
An example of a reusable helper for Node.js and TypeScript:
// src/legaldock.ts
const BASE = 'https://api.legaldock.org/v1';
interface CreateDocumentPayload {
templateId: string;
fields: Record<string, string | number>;
reference: string;
}
interface Signer {
name: string;
email: string;
role: string;
}
export async function createDocument(
apiKey: string,
payload: CreateDocumentPayload
): Promise<{ documentId: string; downloadUrl: string }> {
const res = await fetch(`${BASE}/documents`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: payload.templateId,
fields: payload.fields,
meta: { reference: payload.reference },
}),
});
if (!res.ok) {
const { message } = await res.json() as { message: string };
throw new Error(`LegalDock createDocument: ${message}`);
}
return res.json() as Promise<{ documentId: string; downloadUrl: string }>;
}
export async function requestSignature(
apiKey: string,
documentId: string,
signers: Signer[],
webhookUrl: string,
deadline?: string
): Promise<{ signingSessionId: string }> {
const res = await fetch(`${BASE}/documents/${documentId}/sign`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
signers,
deadline,
notifyOnSigned: 'webhook',
webhookUrl,
}),
});
if (!res.ok) {
const { message } = await res.json() as { message: string };
throw new Error(`LegalDock requestSignature: ${message}`);
}
return res.json() as Promise<{ signingSessionId: string }>;
}
Integrate into your existing codebase:
import { createDocument, requestSignature } from './src/legaldock';
const API_KEY = process.env.LEGALDOCK_API_KEY!;
const WEBHOOK = process.env.LEGALDOCK_WEBHOOK_URL!;
// Called when the accountant onboards a new client employee
export async function issueEmploymentContract(
employeeName: string,
employeeEmail: string,
employerName: string,
employerEmail: string,
startDate: string,
monthlySalary: number,
clientRef: string
) {
const doc = await createDocument(API_KEY, {
templateId: 'ansaettelseskontrakt',
fields: {
medarbejdernavn: employeeName,
virksomhedsnavn: employerName,
startdato: startDate,
maanedsloen: monthlySalary,
arbejdssted: 'Se separat bilag',
},
reference: clientRef,
});
await requestSignature(
API_KEY,
doc.documentId,
[
{ name: employeeName, email: employeeEmail, role: 'employee' },
{ name: employerName, email: employerEmail, role: 'employer' },
],
WEBHOOK,
'2026-07-01'
);
return doc.documentId;
}
Webhooks: receive events automatically
Avoid manual polling, and use webhooks to update your system when documents are signed.
// Express webhook handler
import express from 'express';
import crypto from 'crypto';
const router = express.Router();
router.post('/webhooks/legaldock', express.json(), (req, res) => {
const sig = req.headers['x-legaldock-signature'] as string;
const expected = crypto
.createHmac('sha256', process.env.LEGALDOCK_WEBHOOK_SECRET!)
.update(JSON.stringify(req.body))
.digest('hex');
if (sig !== expected) {
return res.status(401).json({ error: 'Invalid signature' });
}
const { event, documentId, reference } = req.body as {
event: string;
documentId: string;
reference: string;
};
if (event === 'document.signed') {
// Update the client file, send confirmation, archive the PDF
console.log(`Signed: ${documentId} (client ref: ${reference})`);
}
res.json({ ok: true });
});
export default router;
Best practices for accounting firms
Use a sandbox for testing. If LegalDock offers a sandbox environment, use it during integration so test documents do not count against your quota and do not send real emails.
Always store the PDF locally. Download and archive the PDF file in your own system immediately after signing. Use the downloadUrl from the API response.
Set a deadline on signature requests. An NDA that is not signed in time creates confusion. Use the deadline field to manage expectations.
Monitor the error rate. Log all API calls and monitor 4xx and 5xx responses. A sudden rise in 429 errors (rate limit) signals that you need to upgrade the plan or implement backoff.
Error handling: reference table
| HTTP code | Cause | Solution |
|---|---|---|
| 400 | Invalid fields | Check field names against the template specification |
| 401 | Invalid API key | Generate a new key under Settings |
| 403 | Plan restriction | Upgrade your plan |
| 404 | Resource not found | Check the templateId or documentId |
| 429 | Rate limit | Implement exponential backoff |
| 500 | Server error | Contact LegalDock support |
Ready to integrate?
Create a partner account with API access, generate your API key under the settings, and read the full API reference in LegalDock's documentation before you start. If you need help, contact partner support.
This guide is technical guidance and does not constitute legal advice. Contact a lawyer for advice on the documents you generate.
This article is for general guidance only and is not individual legal advice. LegalDock documents are templates — consult a lawyer about your specific situation.