Skip to content

Invoices

Outcome
Create, finalize, render, and deliver an invoice.
Prerequisites
An entity and API key; customer and item data can be inline.
You'll use
Entity key, or account key plus entity_id.

Create

Use the standard Create Invoice API for normal invoice creation. It calculates totals and taxes from your line items and applies the regular document lifecycle. The /custom endpoint is only for imports or integrations that must preserve externally calculated totals exactly.

Minimal invoice with inline customer and one line item:

Create minimaltypescript
// title: Minimal invoice
const _invoice = await sdk.invoices.create({
  customer: { name: "Acme Corp" },
  items: [{ name: "Service", quantity: 1, price: 100 }],
});

Or reference saved data:

Create with refstypescript
// title: Invoice with saved references
const _invoice = await sdk.invoices.create({
  customer_id: "cus_abc123",
  items: [
    { item_id: "itm_xyz789", quantity: 5 },
    { name: "Custom service", quantity: 1, price: 250 },
  ],
});

If your rollout needs gross-discount consumer pricing instead of the default B2B flow, see Calculation Modes.

Finalize

Finalize a draft to assign its invoice number. A finalized document can still be updated with version history until it is fiscalized or voided:

Finalizetypescript
// title: Finalize invoice
// Finalize assigns a document number. Fiscalization, when enabled, is a separate lifecycle concern.
const _finalized = await sdk.documents.finalizeDocument(invoice.id);

Or pass is_draft: false when creating to finalize immediately.

Download PDF

Render pdftypescript
// title: Render PDF
const pdf = await sdk.invoices.renderPdf(invoice.id);

// Save to file
fs.writeFileSync("invoice.pdf", pdf);

// Or send as response
res.setHeader("Content-Type", "application/pdf");
res.send(pdf);

Send by Email

Send emailtypescript
// title: Send invoice
await sdk.email.sendEmail({
  document_id: invoice.id,
  to: invoice.customer.email,
  subject: "Your invoice #{document_number}",
  body_text: "Thank you for your business!",
});

Uses the entity’s default email template. See the Email guide for templates, attachments, and verified custom sender setup, or the Email API for request details.

Optional Invoice Configuration

Early-payment discounts

Use early_payment_discount for conditional terms such as “2% if paid within 10 days.” These terms are separate from line discounts and date_due. Issuing the invoice preserves its full total.

Early paymenttypescript
// title: Conditional early-payment discount
const invoice = await sdk.invoices.create({
  date: "2026-09-01",
  date_due: "2026-10-01",
  currency_code: "EUR",
  customer: { name: "Acme Corp" },
  items: [{ name: "Service", quantity: 1, price: 1000 }],
  early_payment_discount: { percentage: 2, days: 10 },
}, { entity_id: "ent_123" });

// The invoice total stays 1,000. Record only the cash actually received.
await sdk.payments.create({
  document_id: invoice.id,
  amount: 980,
  date: "2026-09-11",
  type: "bank_transfer",
}, { entity_id: "ent_123" });

// The refreshed invoice has total_due: 0 and discount_taken: 20.
const _settled = await sdk.invoices.get(invoice.id, undefined, { entity_id: "ent_123" });

Store reusable terms in entity.settings.early_payment_discount_terms as objects with id, name, percentage, and days. Select one with early_payment_discount.terms_id; explicit percentage or days overrides the selected value. Drafts can change or clear terms. Issued invoices preserve the selected values, deadline, currency precision and issuer timezone even when the reusable terms change. Their issue date, currency and early-payment terms cannot be edited.

The invoicing UI is opt-in: enable Early-payment discounts in the invoice default settings (entity.settings.early_payment_discounts_enabled: true). Omitted, null or false leaves the controls off. Custom white-label settings also include an Early-payment discounts gate (documents.early_payment_discounts); both controls must allow the feature to create offers in the UI. Disabling the controls preserves reusable terms, saved invoice terms, settlement and PDF presentation. These UI controls do not restrict explicit API requests.

The deadline is the issue date plus the specified number of calendar days, inclusive through that date in the issuer’s snapshotted IANA timezone. Payment eligibility uses the recorded effective payment date. Cumulative timely cash must reach the entire discounted balance; partial payments receive no proportional discount. Correcting, deleting or restoring payments recalculates settlement. Full-price payments receive no discount.

The eligible base is the gross invoice amount after ordinary discounts, less applied credits and advances/deposits. Cash received does not reduce that base. The API calculates the discount with decimal arithmetic, rounding half up once to the currency’s minor unit; it does not apply cash-denomination rounding. Terms that round away the entire positive balance are rejected; at least one minor unit must remain payable. Read the returned conditional amounts instead of recalculating them in a client.

For a 1,000.00 EUR invoice with 2% terms, timely cash of 980.00 settles the invoice and records early_payment_discount.discount_taken: 20. Late cash of 980.00 leaves total_due: 20. Payments recorded as coupon count as received funds and can qualify, like other payment methods; credits and advances remain non-cash. total_paid retains its existing meaning, including applied credits and advances; early_payment_discount.total_cash_received reports cash separately, and total_settled includes the realized discount. An overpayment remains visible in the cash and settlement amounts. total_non_cash_applied separately reports applied credits and advances/deposits.

If cash has already earned a discount, applying a later credit or advance preserves eligibility and recalculates the discount on the smaller base. For example, 980.00 paid on time against 1,000.00 earns 20.00; a later 100.00 credit reduces the discount to 18.00 and produces a 98.00 overpayment. The API retains qualification_base to revalidate the original qualifying cash. Removing cash or changing its effective date beyond the deadline can revoke eligibility; reaching the original full-price cash amount also removes the discount. When corrected cash qualifies on a smaller base, that qualification and earlier earned bases remain available for later credits and payment restoration. New invoices paid at full price do not earn one. Automatic linked-advance allocation reserves earned discounts: linking another advance to an already settled invoice consumes none of that advance. Reconciliation and preview planning validate each requested allocation against the resulting settlement, including when that advance triggers the discount.

Bulk e-SLOG archives identify skipped conditional invoices in manifest.json with reason early_payment_discount_unsupported; a selection with no supported exports fails explicitly.

Saved drafts preserve their term values and preset reference even if that preset is later deleted. Re-selecting a current preset or entering custom values can change a draft; issuing it freezes the terms. Concurrent edits that race finalization return 409 so a stale request cannot overwrite the issued state. Saved previews display the document’s draft or void status.

All five PDF templates show the full total, conditional discount, deadline and payable amounts. Fixed-amount UPN, EPC and HUB3 payment codes are omitted because they cannot expire with the discount. Public invoice links display the current saved settlement and terms; the API does not provide a hosted, expiring checkout session. Integrators must recalculate live checkout amounts and expire discounted sessions at the cutoff.

The general invoice and settlement model does not create statutory tax corrections. Unvalidated workflows reject early-payment discounts explicitly: fiscalized issuance, Portugal certified issuance, electronic invoice sending/reporting, EN 16931 UBL/CII, e-SLOG/UJP, Italy SdI/FatturaPA, Poland KSeF, Hungary NAV, Slovenian VOD, KIR/KPR and DDD-DDD exports, miniMAX XML, and QuickBooks CSV. Statutory reports reject a period containing conditional invoices; an entity with discount-adjustment history cannot export those reports until its adapter supports recognition and reversals. Ordinary invoices without these terms continue to work. This boundary is adapter support, not a claim that discounts are legally prohibited in those markets.

For revenue categorization and recognition over a billing period, see Service-Period Invoices.

To show a crypto amount alongside the fiat total, or to price the invoice itself in a crypto asset like BTC, see Crypto Invoicing, Equivalents and Payments.

Exchange rates when updating

Documents in a foreign currency store the exchange rate resolved at creation, with the converted totals, taxes and line amounts. On drafts and estimates, changing currency_code or the exchange-rate reference date (date, date_service or date_service_to) re-derives the rate and every converted amount, and linked payment conversions follow the final rate.

Issued invoices, credit notes and advance invoices, and any document whose rate has source: "manual", keep their stored rate, its source and the converted amounts when a date changes. Item or total changes are converted with that stored rate. Changing the currency of such a document returns 422. To change the currency of an issued document, issue a credit note and a new document in the new currency. An update that races a conflicting change, such as finalization, returns 409.

Other Document Types

Same patterns apply to: