API Reference
Signbee is a document signing API built for AI agents. One API call sends a document for two-party e-signing — both parties sign, both receive a SHA-256 certified PDF.
No SDK, no client library, no build step. Use the native HTTP client in any language — fetch in JavaScript, requests in Python, http.Client in Go. See 20+ framework examples.
Authentication
Signbee supports two modes: with or without an API key. You can start testing immediately without signing up.
With API key Recommended
Sender is pre-verified. Recipient gets the signing email immediately. Best for automated agent workflows and production integrations.
Without API key Quick start
Sender verifies via email OTP first. Good for testing and one-off documents.
Authorization: Bearer YOUR_API_KEY
Ready for production?
Create a free account to get your API key and access the dashboard. 5 documents/month included.
Endpoints
/api/v1/sendSend a document for two-party e-signing. Provide either markdown or a PDF URL.
Auth: Optional — Bearer token or email OTP
Required fields
recipient_name— Full name of the recipientrecipient_email— Email address of the recipientmarkdown— Document content (min 10 chars, max 50KB)Or use pdf_url instead of markdown to send an existing PDF
Required without API key
sender_name— Full name of the sendersender_email— Email address of the senderOptional fields
title— Document title (auto-extracted from first heading if omitted)expires_in_days— Days until signing link expires (default: 7, max: 30)pdf_url— URL to an existing PDF (alternative to markdown)webhook_url— Webhook URL for document.signed events (Pro/Business only, Free returns 403)curl -X POST https://signb.ee/api/v1/send \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"markdown": "# Mutual NDA\n\nThis agreement...",
"recipient_name": "Bob Smith",
"recipient_email": "bob@acme.com"
}'const res = await fetch("https://signb.ee/api/v1/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY",
},
body: JSON.stringify({
markdown: "# Mutual NDA\n\nThis agreement...",
recipient_name: "Bob Smith",
recipient_email: "bob@acme.com",
}),
});
const data = await res.json();
console.log(data.document_id);import requests
res = requests.post(
"https://signb.ee/api/v1/send",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"markdown": "# Mutual NDA\n\nThis agreement...",
"recipient_name": "Bob Smith",
"recipient_email": "bob@acme.com",
},
)
print(res.json()["document_id"]){
"document_id": "cmm...",
"status": "pending_recipient",
"sender": "Alice Chen",
"recipient": "Bob Smith",
"expires_at": "2026-04-19T12:00:00.000Z"
}/api/v1/generateGenerate a PDF from markdown without initiating a signing flow. Useful for previewing documents before sending.
Auth: Not required
Required fields
markdown— Document content (min 10 chars, max 50KB)curl -X POST https://signb.ee/api/v1/generate \
-H "Content-Type: application/json" \
-d '{"markdown": "# Invoice\n\nAmount: $500"}'{
"document_id": "cmm...",
"url": "https://signb.ee/view/cmm...",
"expires_at": "2026-04-16T12:00:00.000Z"
}/api/v1/documents/{id}Get the current status, signing URLs, and PDF links for a document. Use this to poll for completion.
Auth: Required — Bearer token
curl https://signb.ee/api/v1/documents/cmm... \ -H "Authorization: Bearer YOUR_API_KEY"
{
"document_id": "cmm...",
"status": "pending_recipient",
"title": "Mutual NDA",
"sender": { "name": "Alice Chen", "signed_at": "..." },
"recipient": { "name": "Bob Smith", "signed_at": null },
"original_pdf_url": "...",
"signed_pdf_url": null,
"signing_url": "https://signb.ee/sign/...",
"expires_at": "...",
"created_at": "..."
}/api/v1/documents/{id}Revoke a pending document. The signing link becomes invalid immediately.
Auth: Required — Bearer token
{
"success": true,
"message": "Document revoked. The signing link is no longer valid."
}Webhooks (Pro & Business)
Pro and Business plans can receive real-time notifications when documents are signed. Include webhook_url in your POST /api/v1/send request.
Free plan limitation
Free accounts receive HTTP 403 with {"error":"Webhooks require Pro or Business plan. Upgrade at https://signb.ee/dashboard","plan":"FREE"}
Setup
- Include
webhook_urlin your send request - Save the
webhook_secretfrom the response (format:whsec_<uuid>) - When the recipient signs, Signbee POSTs to your webhook_url
curl -X POST https://signb.ee/api/v1/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"markdown": "# Agreement\n\nTerms...",
"recipient_name": "Bob Smith",
"recipient_email": "bob@acme.com",
"webhook_url": "https://your-server.com/webhooks/signbee"
}'{
"document_id": "cmm...",
"status": "pending_recipient",
"sender": "Alice Chen",
"recipient": "Bob Smith",
"expires_at": "2026-09-05T12:00:00.000Z",
"webhook_secret": "whsec_a1b2c3d4e5f6..."
}Webhook Payload
Event: document.signed (only event currently supported)
{
"event": "document.signed",
"document_id": "cmm_...",
"title": "Mutual NDA",
"status": "signed",
"sender_email": "alice@startup.com",
"recipient_name": "Bob Smith",
"recipient_email": "bob@acme.com",
"recipient_signed_at": "2026-08-31T12:00:00.000Z",
"signed_pdf_url": "https://signb.ee/uploads/signed_abc.pdf",
"signature_hash": "e3b0c44298fc1c149afbf4c...",
"verify_url": "https://signb.ee/verify/cmm_...",
"timestamp": "2026-08-31T12:00:00.000Z"
}Headers
Content-Type— application/jsonX-Signbee-Signature— HMAC-SHA256 hex digest of raw POST bodyX-Signbee-Event— document.signedUser-Agent— Signbee-Webhook/1.0Signature Verification
Verify the X-Signbee-Signature header to confirm the webhook came from Signbee. Use timingSafeEqual to prevent timing attacks.
const crypto = require("crypto");
function verifyWebhook(rawBody, signatureHeader, webhookSecret) {
const expected = crypto
.createHmac("sha256", webhookSecret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "utf8"),
Buffer.from(signatureHeader, "utf8")
);
}
// In your Express handler:
app.post("/webhooks/signbee", express.raw({type: "application/json"}), (req, res) => {
const signature = req.headers["x-signbee-signature"];
const webhookSecret = process.env.SIGNBEE_WEBHOOK_SECRET;
if (!verifyWebhook(req.body, signature, webhookSecret)) {
return res.status(401).send("Invalid signature");
}
const payload = JSON.parse(req.body);
console.log(`Document ${payload.document_id} signed!`);
res.json({ received: true });
});Delivery behavior:
- 10-second timeout
- Fire-and-forget (no automatic retries)
- Polling via
GET /api/v1/documents/{id}works as a fallback on all plans
Markdown Tables
GFM (GitHub Flavored Markdown) pipe tables are supported in markdown on all plans.
| Item | Quantity | Price | Total | |------|----------|-------|-------| | Widget A | 5 | $10.00 | $50.00 | | Widget B | 3 | $15.00 | $45.00 | | Widget C | 2 | $25.00 | $50.00 |
Document Lifecycle
Every document moves through a predictable state machine. Poll GET /api/v1/documents/{id} to track progress. On Pro and Business plans, if you set webhook_url, Signbee also POSTs a document.signed event when the recipient signs.
| Status | Meaning |
|---|---|
| draft | PDF generated, no signing flow started |
| pending_sender | Awaiting sender OTP verification |
| pending_recipient | Sender signed, awaiting recipient |
| signed | Both parties signed — signed_pdf_url available |
| expired | Signing link expired before completion |
| revoked | Cancelled via DELETE — signing link invalidated |
The SHA-256 signing certificate is generated when status moves to signed. Both parties receive the certified PDF by email automatically.
How the Signing Flow Works
- 01Agent calls
POST /api/v1/sendwith document content and party details - 02With API key: sender is pre-verified, recipient gets signing email immediately
- 03Without API key: sender verifies via OTP, then recipient gets signing email
- 04Recipient clicks link, reviews the document, and signs
- 05Both parties receive the signed PDF with SHA-256 certificate via email
Agent Integrations
Beyond the REST API, Signbee exposes e-signing to AI agents through two additional protocols. For the full context on agent discoverability, see The Multi-Protocol Future.
MCP Server
Works with Claude Desktop, Cursor, Windsurf, and any MCP-compatible client. Exposes a send_document tool that AI agents can call without writing API code.
{
"mcpServers": {
"signbee": {
"command": "npx",
"args": ["-y", "signbee-mcp"],
"env": { "SIGNBEE_API_KEY": "YOUR_API_KEY" }
}
}
}npm: signbee-mcp · Guide: 2-minute setup
llms.txt
Machine-readable product description for AI agents. Tells LLMs what Signbee can do, how to call the API, and where to find docs — without scraping.
Direct API
Call the REST API from any language. No SDK needed — just HTTP + JSON. See 20+ framework guides with copy-paste examples.
OpenAPI spec: signb.ee/openapi.json
Rate Limits
| Plan | Documents / month | Email rate |
|---|---|---|
| Free | 5 | 1 per minute |
| Pro ($9/mo) | 100 | 10 per minute |
| Business ($19/mo) | Unlimited | 30 per minute |
When you hit a rate limit, the API returns 429 with a Retry-After header. Document limits reset on the 1st of each month.
Error Codes
| Code | Meaning |
|---|---|
| 400 | Missing or invalid fields |
| 401 | Invalid API key |
| 403 | Plan limit reached, webhook_url on Free plan, or unauthorized |
| 429 | Email rate limit exceeded |
| 503 | Email service temporarily unavailable |
All error responses return JSON with an error field:{"error": "description"}
RELATED
Questions?
hello@signb.eeLast updated: 31 August 2026