May 16, 2026 · Automation
Automate Invoice Signing with an API: From Quote to Signed in 30 Seconds
Generate a markdown invoice from your data, send it for signing with one API call, and trigger Stripe payment on completion. The entire flow runs without a human touching a PDF.
Founder, Signbee
TL;DR
Most invoice workflows are needlessly manual. You generate a PDF in QuickBooks, download it, open DocuSign, upload it, place signature fields, send it, wait, then manually reconcile the payment. With an API-first approach, your code generates the invoice as markdown, sends it for signing with one API call, and triggers payment collection when the signature webhook fires. Quote to signed in 30 seconds, not 3 days.
The manual invoice signing workflow is broken
I timed the manual invoice signing process at a mid-size agency. Here's what their accounts team does for every invoice:
Multiply that by 200 invoices a month and you've got someone spending 40 hours — an entire work week — on a process that should be automatic.
The automated flow
Here's the same workflow, automated end-to-end:
Step 1: The markdown invoice template
Your invoice template lives in your codebase. It pulls data from your database — client details, line items, rates, totals — and generates a markdown document that the API converts to a formatted PDF:
interface LineItem {
description: string;
quantity: number;
rate: number;
}
function generateInvoice(params: {
invoiceNumber: string;
clientName: string;
clientEmail: string;
issueDate: string;
dueDate: string;
items: LineItem[];
}) {
const subtotal = params.items.reduce(
(sum, item) => sum + item.quantity * item.rate, 0
);
const tax = subtotal * 0.2; // 20% VAT
const total = subtotal + tax;
const itemRows = params.items
.map(
(item) =>
`| ${item.description} | ${item.quantity} | $${item.rate.toFixed(2)} | $${(item.quantity * item.rate).toFixed(2)} |`
)
.join("\n");
return `
# Invoice ${params.invoiceNumber}
**From:** YourCompany Ltd
**To:** ${params.clientName}
**Issue Date:** ${params.issueDate}
**Due Date:** ${params.dueDate}
---
## Line Items
| Description | Qty | Rate | Amount |
|-------------|-----|------|--------|
${itemRows}
---
| | | **Subtotal** | **$${subtotal.toFixed(2)}** |
|--|--|--|--|
| | | **VAT (20%)** | **$${tax.toFixed(2)}** |
| | | **Total Due** | **$${total.toFixed(2)}** |
## Payment Terms
Payment is due within 30 days of the issue date.
Late payments are subject to 1.5% monthly interest.
By signing below, you confirm receipt of this invoice
and agree to the payment terms stated above.
`;
}Step 2: Send for signing via API
With the markdown generated, send it to the Signbee API in one call:
async function sendInvoiceForSigning(invoice: {
invoiceNumber: string;
clientName: string;
clientEmail: string;
issueDate: string;
dueDate: string;
items: LineItem[];
}) {
const markdown = generateInvoice(invoice);
const response = await fetch("https://signb.ee/api/v1/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer sk_live_your_api_key",
},
body: JSON.stringify({
markdown,
recipient_name: invoice.clientName,
recipient_email: invoice.clientEmail,
subject: `Invoice ${invoice.invoiceNumber} — Please review and sign`,
}),
});
const { id, status } = await response.json();
// Store the document ID against the invoice
await db.invoices.update({
where: { number: invoice.invoiceNumber },
data: { signbeeDocId: id, signingStatus: status },
});
return { id, status };
}The API receives the markdown, generates a clean PDF with your invoice layout, and emails it to the client. The client sees a professional invoice with a "Sign" button. No PDF library on your end. No template builder. No manual steps.
Step 3: Handle the signature webhook
When the client signs, Signbee fires a webhook to your server. This is where you trigger the payment flow:
import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: NextRequest) {
const payload = await req.json();
if (payload.event === "document.signed") {
// Find the invoice linked to this document
const invoice = await db.invoices.findFirst({
where: { signbeeDocId: payload.document_id },
});
if (!invoice) return NextResponse.json({ error: "Not found" }, { status: 404 });
// Create a Stripe payment link
const session = await stripe.checkout.sessions.create({
mode: "payment",
line_items: [{
price_data: {
currency: "usd",
unit_amount: Math.round(invoice.totalAmount * 100),
product_data: {
name: `Invoice ${invoice.number}`,
},
},
quantity: 1,
}],
success_url: `${process.env.APP_URL}/invoices/${invoice.id}/paid`,
cancel_url: `${process.env.APP_URL}/invoices/${invoice.id}`,
});
// Update invoice status and send payment link
await db.invoices.update({
where: { id: invoice.id },
data: {
signingStatus: "signed",
signedAt: new Date(),
paymentUrl: session.url,
},
});
// Email the payment link to the client
await sendPaymentEmail(invoice.clientEmail, session.url!);
}
return NextResponse.json({ received: true });
}The complete flow in one diagram
| Step | Actor | Time |
|---|---|---|
| Quote approved in CRM | Your app | 0s |
| Invoice markdown generated | Your code | <1s |
| Sent to Signbee API | fetch() | <2s |
| Client receives email | Signbee | <30s |
| Client signs invoice | Signer | ~2 min |
| Webhook fires | Signbee | instant |
| Stripe payment link sent | Your webhook | <2s |
From the moment a quote is approved in your CRM, the client can have a signed invoice and a payment link in their inbox in under a minute. No human intervention.
Why DocuSign doesn't work for this
I tried building this exact flow with DocuSign. Here's where it fell apart:
Template management. DocuSign requires you to upload a PDF template to their dashboard, position signature fields manually, and save it with a template ID. Every time your invoice layout changes, someone logs into the dashboard and repositions fields. With Signbee, the template is a function in your code — version-controlled and dynamic.
Dynamic line items. DocuSign's template system doesn't support variable-length tables. If one invoice has 3 line items and another has 15, you need separate templates or workarounds with "supplemental documents." With markdown, you generate whatever table you need — 3 rows or 300.
Cost at volume. An agency sending 200 invoices per month pays $100/month on Signbee ($0.50/doc). DocuSign's API plan for that volume requires the $300/month tier. And you're locked into an annual contract. See our full pricing comparison.
Connecting to accounting tools
The webhook-driven architecture makes it straightforward to connect the signing flow to any accounting or payment tool:
| Tool | Trigger |
|---|---|
| Stripe | document.signed |
| QuickBooks | document.signed |
| Xero | document.signed |
| Slack | document.signed |
| Zapier / n8n | document.signed |
For more on handling webhook events reliably, see our complete webhooks guide.
Batch invoicing at month-end
Many businesses send invoices in batches — 50 or 200 at the end of the month. Signbee's rate limits handle this without throttling: 1,000 requests/min on paid plans. For batch sending patterns, see our batch sending guide.
Frequently Asked Questions
Can I automate invoice signing with an API?
Yes. Generate the invoice as markdown from your database, POST it to the Signbee API with recipient details, and the invoice is emailed for signing automatically. The entire flow from generation to delivery takes under 30 seconds.
How do I connect invoice signing to Stripe?
Listen for the document.signed webhook event. When it fires, create a Stripe Checkout Session or Payment Intent for the invoice amount and email the payment link to the client. The signing and payment steps are fully decoupled but automated.
Is a signed invoice legally binding?
Yes. Electronic signatures on invoices are valid under the ESIGN Act, UETA, and eIDAS. Signbee generates SHA-256 audit trails with timestamps and IP addresses for every signature.
What format should automated invoices use?
Markdown. Write the invoice as a template function in your codebase, inject dynamic data (client name, line items, totals), and let the API convert it to a formatted PDF. No PDF library, no LaTeX, no template builder.
Automate your invoice workflow — 5 free docs/month, $0.50/doc after.
Last updated: May 16, 2026 · Michael Beckett is the founder of Signbee and B2bee Ltd.