Invoices

Bill once, collect exactly

GenesisPay invoices are one-off commercial billing documents. They reuse saved customers, support manual tax and discount rates, render as a hosted page and PDF, and collect through the canonical GenesisPay payment flow.

Create and send an invoice

Seller SDK
import { GenesisPay } from "@genesis-tech/genesispay-seller";

const genesispay = new GenesisPay({
  apiKey: process.env.GENESISPAY_SELLER_KEY!,
});

const customer = await genesispay.customers.create({
  name: "Ada Lovelace",
  email: "ada@example.com",
  companyName: "Analytical Engines Ltd",
  addressLine1: "1 Example Street",
  city: "London",
  postalCode: "SW1A 1AA",
  countryCode: "GB",
});

const draft = await genesispay.invoices.create({
  customerId: customer.publicId,
  asset: "EURC",
  dueAt: "2026-08-31T23:59:59.999Z",
  discountBps: 500,
  lineItems: [
    { description: "Consulting", quantity: 2, unitAmount: "450.00",
      taxConfig: { version: 1, treatment: "taxable", rateBps: 2300, note: null } },
  ],
});

const invoice = await genesispay.invoices.finalize(draft.publicId);

await genesispay.invoices.send(invoice.publicId, {
  idempotencyKey: `initial-${invoice.publicId}`,
});

unitAmount is a decimal string in the invoice's asset. Every response total ending in Minor is an integer string, so no float crosses the money boundary.

Lifecycle and payment truth

Invoice states
draft → open → paid
             ↘ void
             ↘ uncollectible

open becomes past_due after dueAt; it remains payable.
paid is derived only from a confirmed, non-simulated payment.

Drafts are editable, but they have no number, hosted URL, PDF, or payment link. Finalization is the commit point: it assigns the invoice number, snapshots seller/customer/line details, and creates exactly one single-use payment link. Finalized invoices cannot be edited.

Neither the dashboard nor the API can set paid. It is a read-only projection of GenesisPay's verified settlement record, excluding simulated test payments. A confirmed payment wins a race with void or write-off so moved money is never hidden.

Tax and accounting scope

Each line declares its own tax treatment and rate in basis points:2300 means 23%. New prices include tax. Discounts reduce each line's gross price before its tax is calculated. Existing legacy invoices keep their original calculation. GenesisPay freezes the arithmetic, but it does not determine tax jurisdiction, issue government-certified fiscal documents, file returns, or provide tax advice. Set the seller's legal details and tax registrations through KYB before finalizing.

Email delivery

invoices.send sends the hosted invoice link and attaches the PDF through the deployment's configured Resend account. Supply a stable idempotencyKey for each intended send; retries with the same key return the same delivery instead of sending another email. Configure RESEND_KEY and a verified RESEND_FROM_EMAIL sender in production.

After verified payment, the confirmation includes the original invoice and a separate payment receipt referencing the same invoice number. Product and payment-link checkouts generate both automatically; they do not create a second payment request.

Buyer details at checkout

Product and payment-link checkouts show the buyer's billing details before payment, with an Edit option. A signed-in buyer can explicitly save a default; otherwise edits apply only to that purchase. Verified merchant identity and issued documents are never changed by buyer edits. Billing details are not a delivery address.

Continuing preserves a temporary, browser-bound billing draft for up to 24 hours, so refresh or a funding return can restore it. External wallets have no permanent billing default. Recovery never authorizes payment, and expired or unavailable drafts require another review.

Operators: the cron-secret-only POST /api/v1/invoices/reconcile-checkout-documents also removes expired temporary drafts in bounded batches and returns an expiredBillingDrafts count. This housekeeping does not delete issued invoices, receipts or payment records. Seller API keys cannot invoke this operational endpoint.

Choose the right billing primitive

Use invoices for a specific customer and amount. Use a payment link for lightweight checkout, or subscription plans for recurring charges authorized by a payer mandate.