All posts
tutorial
Build an AI Invoice Generator App with AI Pass SDK
Build an AI invoice generator for freelancers and small businesses using the AI Pass SDK. Full code and deployment guide included.
EiliyaMarch 17, 20264 min read
Build an AI Invoice Generator App with AI Pass SDK
Invoice generators have high repeat usage — once freelancers find a good tool, they use it every time they invoice. Here's how to build one.
Step 1: Get Your Client ID
- Sign up at aipass.one, verify email
- Developer Dashboard → OAuth2 Clients → Create client
- Copy your Client ID
Step 2: The App
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AI Invoice Generator</title>
<link href="https://aipass.one/aipass-ui.css" rel="stylesheet">
<style>
body { font-family: sans-serif; background: #0f0f0f; color: #f0f0f0; max-width: 800px; margin: 0 auto; padding: 40px 20px; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.full { grid-column: 1/-1; }
.form-group { margin-bottom: 14px; }
label { display: block; margin-bottom: 5px; color: #aaa; font-size: 0.85rem; }
input, select, textarea { width: 100%; padding: 10px 12px; background: #1a1a1a; border: 1px solid #2a2a2a; border-radius: 8px; color: #f0f0f0; box-sizing: border-box; }
.section-title { color: #16a085; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.05em; margin: 20px 0 12px; }
.line-item { display: grid; grid-template-columns: 3fr 1fr 1fr auto; gap: 8px; margin-bottom: 8px; align-items: center; }
.rm { padding: 8px; background: #333; border: none; border-radius: 6px; color: #f0f0f0; cursor: pointer; }
.add-btn { width: 100%; padding: 10px; background: transparent; border: 1px dashed #444; border-radius: 8px; color: #888; cursor: pointer; margin-bottom: 20px; }
.gen-btn { width: 100%; padding: 15px; background: #16a085; border: none; border-radius: 10px; color: white; font-size: 1.05rem; font-weight: 600; cursor: pointer; }
.gen-btn:disabled { background: #333; cursor: not-allowed; }
.loading { display: none; text-align: center; padding: 30px; color: #888; }
.result { display: none; margin-top: 24px; }
.invoice-box { background: white; color: #111; border-radius: 10px; padding: 32px; white-space: pre-wrap; line-height: 1.8; font-family: Georgia, serif; }
.copy-btn { margin-top: 12px; padding: 10px 22px; background: #16a085; border: none; border-radius: 8px; color: white; cursor: pointer; }
</style>
</head>
<body>
<h1 style="margin-bottom:6px;">🧾 AI Invoice Generator</h1>
<p style="color:#888;margin-bottom:28px;">Professional invoices in seconds</p>
<div class="section-title">From (You)</div>
<div class="grid">
<div class="form-group"><label>Name / Business</label><input type="text" id="fromName" placeholder="Jane Smith Design"></div>
<div class="form-group"><label>Email</label><input type="email" id="fromEmail" placeholder="jane@example.com"></div>
</div>
<div class="section-title">To (Client)</div>
<div class="grid">
<div class="form-group"><label>Client Name</label><input type="text" id="toName" placeholder="Acme Corp"></div>
<div class="form-group"><label>Client Email</label><input type="email" id="toEmail" placeholder="accounts@acme.com"></div>
</div>
<div class="section-title">Details</div>
<div class="grid">
<div class="form-group"><label>Invoice #</label><input type="text" id="invNum" value="INV-001"></div>
<div class="form-group"><label>Currency</label>
<select id="currency"><option>USD</option><option>EUR</option><option>GBP</option></select>
</div>
<div class="form-group"><label>Invoice Date</label><input type="date" id="invDate"></div>
<div class="form-group"><label>Due Date</label><input type="date" id="dueDate"></div>
<div class="form-group"><label>Payment Terms</label>
<select id="terms"><option>NET 14</option><option>NET 30</option><option>Due on receipt</option></select>
</div>
<div class="form-group"><label>Payment Method</label><input type="text" id="payMethod" placeholder="Bank transfer, PayPal..."></div>
</div>
<div class="section-title">Line Items</div>
<div id="lineItems">
<div class="line-item">
<input class="desc" type="text" placeholder="Service description">
<input class="qty" type="number" value="1" min="0">
<input class="rate" type="number" value="0" min="0" placeholder="Rate">
<button class="rm" onclick="removeItem(this)">✕</button>
</div>
</div>
<button class="add-btn" onclick="addItem()">+ Add Line Item</button>
<div class="form-group">
<label>Notes (optional)</label>
<textarea id="notes" rows="2" placeholder="Late payments subject to 1.5% monthly interest..."></textarea>
</div>
<button class="gen-btn" id="genBtn" onclick="generateInvoice()">✨ Generate Professional Invoice</button>
<div class="loading" id="loading">Generating your invoice...</div>
<div class="result" id="result">
<div class="invoice-box" id="invoiceText"></div>
<button class="copy-btn" onclick="navigator.clipboard.writeText(document.getElementById('invoiceText').textContent).then(()=>alert('Copied!'))">📋 Copy Invoice</button>
</div>
<script src="https://aipass.one/aipass-sdk.js"></script>
<script>
AiPass.initialize({ clientId: 'YOUR_CLIENT_ID', requireLogin: true, darkMode: true });
// Set default dates
const today = new Date(), due = new Date(today);
due.setDate(due.getDate() + 14);
document.getElementById('invDate').value = today.toISOString().split('T')[0];
document.getElementById('dueDate').value = due.toISOString().split('T')[0];
function addItem() {
const d = document.createElement('div'); d.className = 'line-item';
d.innerHTML = '<input class="desc" type="text" placeholder="Service description"><input class="qty" type="number" value="1"><input class="rate" type="number" value="0"><button class="rm" onclick="removeItem(this)">✕</button>';
document.getElementById('lineItems').appendChild(d);
}
function removeItem(btn) {
if (document.querySelectorAll('.line-item').length > 1) btn.closest('.line-item').remove();
}
async function generateInvoice() {
const items = []; let total = 0;
const currency = document.getElementById('currency').value;
document.querySelectorAll('.line-item').forEach(r => {
const desc = r.querySelector('.desc').value;
const qty = parseFloat(r.querySelector('.qty').value) || 0;
const rate = parseFloat(r.querySelector('.rate').value) || 0;
if (desc) { const amt = qty * rate; total += amt; items.push({desc, qty, rate, amt}); }
});
document.getElementById('genBtn').disabled = true;
document.getElementById('loading').style.display = 'block';
document.getElementById('result').style.display = 'none';
const prompt = `Create a professional invoice:
FROM: ${document.getElementById('fromName').value} (${document.getElementById('fromEmail').value})
TO: ${document.getElementById('toName').value} (${document.getElementById('toEmail').value})
INVOICE #: ${document.getElementById('invNum').value}
DATE: ${document.getElementById('invDate').value} | DUE: ${document.getElementById('dueDate').value}
TERMS: ${document.getElementById('terms').value} | METHOD: ${document.getElementById('payMethod').value}
CURRENCY: ${currency}
ITEMS:
${items.map(i => `- ${i.desc}: ${i.qty} × ${i.rate} ${currency} = ${i.amt.toFixed(2)} ${currency}`).join('
')}
TOTAL: ${total.toFixed(2)} ${currency}
NOTES: ${document.getElementById('notes').value || 'Late payments subject to 1.5% monthly interest.'}
Format as complete professional invoice, ready to send. Clean, clear, professional.`;
try {
const r = await AiPass.generateCompletion({
model: 'gpt-5-mini', temperature: 1, max_tokens: 16000,
messages: [
{ role: 'system', content: 'Professional invoice formatter.' },
{ role: 'user', content: prompt }
]
});
document.getElementById('invoiceText').textContent = r.choices[0].message.content;
document.getElementById('result').style.display = 'block';
} catch(e) { console.error(e); alert('Error — try again.'); }
finally { document.getElementById('loading').style.display = 'none'; document.getElementById('genBtn').disabled = false; }
}
</script>
</body>
</html>
Key Pattern
AiPass.initialize({ clientId: 'YOUR_CLIENT_ID', requireLogin: true, darkMode: true });
const r = await AiPass.generateCompletion({
model: 'gpt-5-mini',
temperature: 1, // Required for GPT-5
max_tokens: 16000, // Required for complete output
messages: [...]
});
const text = r.choices[0].message.content;
Deploy & Earn
Freelancers invoice weekly. High repeat usage = consistent commission.
Deploy anywhere: GitHub Pages, Netlify, Vercel, or publish on AI Pass catalog.
50% commission on every API call via your Client ID.
Live demo: aipass.one/apps/invoice-gen Developer Dashboard: aipass.one/panel/developer