Markdown to Signed PDF API: Send Contracts in One POST Request
Convert markdown documents into legally binding, two-party signed PDFs with a single HTTP request. No SDK, no template builder, no pre-built forms. Just POST markdown to https://signb.ee/api/v1/send and get SHA-256 certified signatures back via webhook.
Founder, Signbee
Send a single POST request to https://signb.ee/api/v1/send with markdown content and signer details. The API compiles the PDF, sends signing links via Amazon SES, and returns a document ID. No API key required for first send (OTP verification). Signed documents include tamper-proof SHA-256 audit certificates.
Why Markdown for Contracts?
Traditional e-signature platforms force you to upload static PDFs or use visual template builders to position signature fields at exact X/Y pixel coordinates. When contract text changes (a clause is added, a paragraph wraps to a new line), signature boxes land in the wrong place.
Markdown-based contract APIs solve this. You write agreement text in plain markdown, store it in Git under version control, and inject dynamic variables using standard template literals. The API server compiles the markdown into a professional PDF at runtime, automatically placing signature blocks at the end.
API-First Benefits
- No visual template builder required — contracts live in your codebase
- Version control with Git — review legal changes via pull requests
- Dynamic content injection with template variables
- Automatic page breaks and signature block placement
- SHA-256 tamper-proof audit certificates included
API Endpoint: POST /api/v1/send
The POST /api/v1/send endpoint accepts markdown content and party details, compiles the PDF, and sends signing links to both parties via Amazon SES. Returns a document ID for tracking signature status.
Request Format
{
"markdown": "# Consulting Agreement\n\n**Effective Date:** 2026-09-09...",
"recipient_name": "Jane Doe",
"recipient_email": "jane@example.com",
"subject": "Consulting Agreement for Review",
"metadata": {
"contract_type": "consulting",
"deal_id": "deal_12345"
}
}Optional: API Key for Instant Send
If you include a Bearer token in the Authorization header, the document is sent instantly. Without an API key, the sender receives an email OTP to verify their identity before the send completes.
curl -X POST https://signb.ee/api/v1/send \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"markdown": "# NDA\n\n**Parties:** Acme Corp and Jane Doe...",
"recipient_name": "Jane Doe",
"recipient_email": "jane@example.com"
}'Response
{
"id": "doc_abc123xyz",
"status": "pending",
"signing_url": "https://signb.ee/sign/abc123xyz",
"created_at": "2026-09-09T14:23:45Z"
}Example: JavaScript / Node.js
Here's a complete Node.js function that sends a consulting agreement for signature. The markdown content includes dynamic variables injected via template literals.
async function sendConsultingAgreement({
consultantName,
clientName,
clientEmail,
hourlyRate,
scopeSummary,
effectiveDate
}) {
const markdown = `# Consulting Services Agreement
**Effective Date:** ${effectiveDate}
**Consultant:** ${consultantName}
**Client:** ${clientName} (${clientEmail})
**Hourly Rate:** $${hourlyRate} USD
---
## 1. Scope of Work
The Consultant agrees to provide the following services:
> ${scopeSummary}
## 2. Payment Terms
Invoices will be submitted bi-weekly. Payment is due within 30 days.
## 3. Intellectual Property
All work product transfers to the Client upon full payment.
## 4. Confidentiality
Both parties agree to keep proprietary information confidential.`.trim();
const response = await fetch("https://signb.ee/api/v1/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY" // optional
},
body: JSON.stringify({
markdown,
recipient_name: clientName,
recipient_email: clientEmail,
subject: `Consulting Agreement: ${consultantName} & ${clientName}`,
metadata: {
contract_type: "consulting_v1",
consultant: consultantName
}
})
});
if (!response.ok) {
throw new Error(`Failed to send: ${response.statusText}`);
}
return response.json();
}
// Usage
const result = await sendConsultingAgreement({
consultantName: "John Smith",
clientName: "Acme Corp",
clientEmail: "legal@acme.com",
hourlyRate: 150,
scopeSummary: "Backend API development and database optimization",
effectiveDate: "2026-09-09"
});
console.log("Document ID:", result.id);
console.log("Signing URL:", result.signing_url);Example: Python (requests)
Python example using the requests library. This sends an NDA for signature.
import requests
def send_nda(disclosing_party, receiving_party, receiving_email, effective_date):
markdown = f"""# Mutual Non-Disclosure Agreement
**Effective Date:** {effective_date}
**Disclosing Party:** {disclosing_party}
**Receiving Party:** {receiving_party}
---
## 1. Definition of Confidential Information
"Confidential Information" means all proprietary data, trade secrets, and technical information.
## 2. Obligations
The Receiving Party agrees to hold Confidential Information in strict confidence.
## 3. Term
This agreement remains in effect for two (2) years from the Effective Date.
""".strip()
response = requests.post(
"https://signb.ee/api/v1/send",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY" # optional
},
json={
"markdown": markdown,
"recipient_name": receiving_party,
"recipient_email": receiving_email,
"subject": f"NDA: {disclosing_party} & {receiving_party}"
}
)
response.raise_for_status()
return response.json()
# Usage
result = send_nda(
disclosing_party="Acme Corp",
receiving_party="Jane Doe",
receiving_email="jane@example.com",
effective_date="2026-09-09"
)
print(f"Document ID: {result['id']}")
print(f"Status: {result['status']}")SHA-256 Audit Certificates
Every signed document includes a tamper-proof SHA-256 certificate of completion. The certificate is a separate PDF file that contains:
Certificate Contents
- Unix timestamps for document creation and signature completion
- IP addresses and user agent strings of all signers
- Email verification hashes (proving email delivery and access)
- SHA-256 checksums of the document before and after signing
- Legal compliance statement (ESIGN Act, eIDAS, ECA 2000)
The certificate is generated by the server after both parties sign. You can download it via the API using the document ID:
GET https://signb.ee/api/v1/documents/{document_id}/certificate
Authorization: Bearer YOUR_API_KEYWebhooks (Pro & Business Plans)
Pro and Business plans support webhook callbacks when documents are signed. Pass a webhook_url parameter in your API request, and the server will POST a document.signed event to your endpoint when the signature is complete.
{
"event": "document.signed",
"document_id": "doc_abc123xyz",
"recipient_email": "jane@example.com",
"timestamp": "2026-09-09T15:30:00Z",
"metadata": {
"contract_type": "consulting_v1"
},
"download_url": "https://signb.ee/api/v1/documents/doc_abc123xyz/download",
"certificate_url": "https://signb.ee/api/v1/documents/doc_abc123xyz/certificate"
}Webhook payloads include HMAC-SHA256 signatures in the x-signbee-signature header for verification. See our webhook security guide for implementation details.
The Markdown-to-PDF Box Model & Typography Engine
Under the hood, converting markdown text to an executive-ready contract PDF is far more nuanced than running an HTML-to-PDF headless browser script. Headless Chromium instances are notoriously heavy, memory-hungry, and vulnerable to sandbox escapes. Signbee utilizes an ultra-fast, native typographic layout engine compiled to WebAssembly:
Deterministic Typography Rules:
- Proportional Typographic Scale: Document titles render at 22pt bold, Section headings at 15pt semibold, and legal prose at 10.5pt with 15pt proportional line leading to guarantee maximum readability.
- Defensive Pagination: Headings automatically measure the remaining vertical point budget on the current page. If fewer than 72 points remain, the engine automatically breaks to the next page, eliminating orphan headings.
- Table Auto-Fitting: Multi-column tables dynamically compute column widths based on content density, wrapping table cell prose without clipping or overflow.
Example: Golang High-Throughput Pipeline
For microservices written in Go requiring high-throughput contract generation, you can dispatch agreements using native net/http:
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
type SendRequest struct {
Markdown string `json:"markdown"`
RecipientName string `json:"recipient_name"`
RecipientEmail string `json:"recipient_email"`
Subject string `json:"subject"`
}
func main() {
payload := SendRequest{
Markdown: "# Independent Contractor Agreement\n\nBetween Acme Labs and John Doe...",
RecipientName: "John Doe",
RecipientEmail: "john.doe@example.com",
Subject: "Please review and sign your contractor agreement",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://signb.ee/api/v1/send", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+os.Getenv("SIGNBEE_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Printf("Status: %s\n", resp.Status)
}Custom Font Subsetting & Document Compression
One common issue with traditional PDF generation libraries is bloated file sizes. Embedding full multi-megabyte TrueType or OpenType font files for Latin, CJK, and typographic symbols causes PDFs to balloon to 8MB+ for simple three-page agreements.
Signbee solves this using dynamic glyph analysis and WebAssembly font subsetting. When your markdown is compiled, the parser audits the exact Unicode codepoints used throughout the document, generates a stripped binary font subset containing only the glyphs present, and embeds that compact font table directly into the PDF. As a result, signed legal documents maintain crisp typographic fidelity across any operating system or PDF reader while clocking in at under 120KB per document. This ultra-lean payload size guarantees lightning-fast email dispatches and instant mobile viewing over spotty cellular networks.
Frequently Asked Questions
What markdown features are supported?
Standard markdown is fully supported: headings, bold, italic, lists, blockquotes, code blocks, horizontal rules, and links. Tables are supported on Pro and Business plans. Custom CSS classes for page breaks and margins are available for advanced styling.
Can I send the same markdown to multiple recipients?
Yes. Call POST /api/v1/send multiple times with the same markdown content but different recipient_email values. Each recipient gets a unique signing link and document ID. For bulk sending, consider using a loop with rate limit handling (see our batch API guide).
Are these signatures legally binding?
Yes. Signed documents include SHA-256 audit certificates that satisfy the ESIGN Act (US), eIDAS (EU), and ECA 2000 (UK) requirements for intent, consent, attribution, and tamper-evident integrity. The certificate includes cryptographic checksums, email verification hashes, and signing timestamps. See our legal guide for details.
Related resources
Ready to send contracts in one API call?
POST markdown to signb.ee/api/v1/send and get SHA-256 certified signatures back. Free tier: 5 documents/month, no credit card required.