PromptInvoice Open the generator

PromptInvoice for agents

An AI agent can make an invoice, quote, estimate, receipt or payment voucher as a finished PDF with one HTTP request. The PDF is identical to the one the Download PDF button produces. No account, no key, nothing stored.

The whole API in one line: POST https://invoice.flowsxr.com/api/pdf with the document as JSON. You get application/pdf back. Send GET to the same URL for a machine-readable version of this page.

Quick start

curl -sS https://invoice.flowsxr.com/api/pdf \
  -H 'Content-Type: application/json' \
  -o invoice.pdf \
  -d '{
    "number": "INV-0042",
    "from": { "name": "Studio Nova Ltd", "email": "billing@studionova.com" },
    "to":   { "name": "Acme Corp", "email": "ap@acme.com" },
    "items": [ { "description": "Prototype development", "qty": 24, "rate": 120 } ],
    "currency": "NZD", "taxRate": 15, "taxLabel": "GST"
  }'

Python

import requests

doc = {"number": "INV-0042", "from": {"name": "Studio Nova Ltd"}, "to": {"name": "Acme Corp"},
       "items": [{"description": "Prototype development", "qty": 24, "rate": 120}], "currency": "NZD"}
r = requests.post("https://invoice.flowsxr.com/api/pdf", json=doc, timeout=60)
if r.status_code == 400:
    print(r.json()["details"])          # [{"field": "...", "message": "..."}]: fix and resend
r.raise_for_status()
open("INV-0042.pdf", "wb").write(r.content)

JavaScript

const r = await fetch('https://invoice.flowsxr.com/api/pdf', {
  method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(doc),
});
if (!r.ok) throw new Error(JSON.stringify(await r.json()));
const pdf = new Uint8Array(await r.arrayBuffer());

Choosing the document type

docTypeUse it whenNotes
invoiceAsking a client to pay for work or goodsDefault. Due date defaults to 14 days after the issue date.
quote / estimateProposing a price before work startsdueDate is printed as "Valid until".
receiptConfirming a payment you receiveddueDate is printed as "Paid on"; the PDF shows PAID.
voucherRecording money you paid out (a contractor, staff, a supplier)"Pay to" replaces "Bill to"; adds Approved by / Received by signature lines; no due date; no default note.

Every field

Only number, from.name, to.name and at least one item are required. Everything else has a sensible default. Unknown fields are ignored and reported back as warnings.

FieldTypeDefaultMeaning
docTypetextinvoiceinvoice, quote, estimate, receipt or voucher
numbertext, requiredYour document number, e.g. INV-0042, PV-2026-014. PromptInvoice does not number API documents for you.
issueDateYYYY-MM-DDtoday (UTC)Issue date; for vouchers, the voucher date
dueDateYYYY-MM-DDissue + 14 daysDue, valid-until or paid-on date (ignored for vouchers)
fromobjectYour business: name (required), email, phone, address (use \n for new lines), taxId, logo, signature
toobjectThe client or payee: name (required), email, address, reference (PO or project ref)
itemslist1 to 200 lines of { "description", "qty", "rate" }. rate is the unit price; qty defaults to 1 and may be hours (16.48).
currencyISO 4217USD150+ codes, e.g. USD, SGD, NZD, EUR, GBP, INR, LKR. Sets the symbol and formatting.
taxRatenumber 0 to 1000Percent applied after discount
taxLabeltextTaxGST, VAT, Sales tax
discountTypepercent or fixedpercentHow discountValue is read
discountValuenumber0Percent (0 to 100) or an amount; capped at the subtotal
shippingnumber0Added after tax
customFieldslistnoneUp to 10 { "label", "value" } rows shown in the header, e.g. Project, PO number
paymentDetailstextemptyBank details or how to pay
paymentMethodtextemptyVouchers: Bank transfer, Cash, PayNow, Cheque
approvedBytextemptyVouchers: name printed under the Approved by signature
notestexta thank-you line (none for vouchers)Footer text; send "" for none
theme#rrggbb#166534Accent colour
layoutstacked or sidestackedside places From and To side by side

Never send totals. Subtotal, discount, tax and total are always calculated from the items, exactly as the app does, so the PDF always adds up. A total field is ignored with a warning.

Examples

Payment voucher (paying a contractor)

{
  "docType": "voucher",
  "number": "PV-2026-014",
  "issueDate": "2026-10-02",
  "from": { "name": "Studio Nova Ltd", "email": "billing@studionova.com", "address": "12 Example Street\nAuckland 1010" },
  "to": { "name": "Jane Contractor", "email": "jane@example.com" },
  "items": [
    { "description": "Design services, September 2026", "qty": 1, "rate": 350 },
    { "description": "Advance for October 2026 (deducted from the October payment)", "qty": 1, "rate": 200 }
  ],
  "currency": "SGD",
  "paymentMethod": "Bank transfer",
  "approvedBy": "Alex Owner"
}

Invoice with tax, discount and bank details

{
  "number": "INV-0042",
  "issueDate": "2026-10-02",
  "dueDate": "2026-10-16",
  "from": { "name": "Studio Nova Ltd", "taxId": "123-456-789", "address": "12 Example Street\nAuckland 1010" },
  "to": { "name": "Acme Corp", "email": "ap@acme.com", "reference": "PO-2026-014" },
  "items": [
    { "description": "Mixed-reality prototype: Unity development", "qty": 24, "rate": 120 },
    { "description": "On-site user testing session", "qty": 2, "rate": 450 }
  ],
  "currency": "NZD", "taxRate": 15, "taxLabel": "GST",
  "discountType": "percent", "discountValue": 5,
  "customFields": [ { "label": "Project", "value": "September prototype" } ],
  "paymentDetails": "Bank: Example Bank\nAccount: 01-0000-0000000-00\nReference: INV-0042"
}

Logo and signature

Send images inline as base64 data URIs (PNG, JPEG, WebP or SVG, up to 1 MB each). Links to images are not fetched. The signature is printed above "Approved by" on vouchers and as the authorised signature on other documents.

import base64
logo = "data:image/png;base64," + base64.b64encode(open("logo.png", "rb").read()).decode()
doc["from"]["logo"] = logo

Responses and errors

StatusBodyWhat to do
200The PDF. Content-Disposition carries a filename like INV-0042 - Acme Corp.pdfSave it. If X-PromptInvoice-Warnings is present, it lists ignored fields.
400{ "error", "details": [{ "field", "message" }], "warnings" }Every problem is listed at once. Fix those fields and resend.
413{ "error" }Body over 4 MB: shrink the logo or signature.
500{ "error", "message" }Rendering failed. Retry once after a few seconds.
{
  "error": "The document has problems. Fix the fields listed and send it again.",
  "details": [
    { "field": "number", "message": "is required" },
    { "field": "items[0].rate", "message": "must be a number (the unit price)" }
  ]
}

The first request after a quiet period can take a few seconds while the renderer starts. Later ones take about a second.

Rules for agents working for a person

  1. Use only figures the person gave you or that come from their records. Never invent rates, hours, tax rates or bank details.
  2. Pick the right type. Money coming in is an invoice (or a receipt once paid). Money going out is a voucher.
  3. Show a summary before you generate: type, number, payee or client, each line, currency and the total you expect. Generate after they confirm.
  4. Keep numbering consistent with the person's existing documents (ask for the last number if you do not know it).
  5. Dates are YYYY-MM-DD. If the person says "today", use their local date, not yours.
  6. Hand back the file, named as the Content-Disposition suggests, and say where you saved it. Sending it to anyone is the person's decision.
  7. The API does not save anything. If the person wants the document in their PromptInvoice history, they can recreate it in the generator at invoice.flowsxr.com and press Save.

Limits and privacy