Invoices
Invoices let you bill specific customers with line items, tax, and a one-click payment link. The customer receives an email with a pay button that opens the hosted checkout.
Full flow
An invoice follows this lifecycle: DRAFT → OPEN → PAID. You can also VOID an unpaid invoice at any time.
Step 1: Create an invoice
Step 2: Open the invoice
Transition the invoice from DRAFT to OPEN. Once open, the invoice is finalized and can be paid.
Step 3: Send to customer
Send the invoice via email. The customer receives an email with the invoice details and a pay button that opens the hosted checkout.
One step
open and send separately, or just call send which will automatically open a draft invoice before sending.Step 4: Check status
No extra calls needed
paymentIntent object is automatically included once the customer has paid. You don't need to make a separate call to paymentIntents.retrieve().List invoices
Void an invoice
Void an unpaid invoice. This marks it as cancelled and prevents the customer from paying.
Webhooks
| Event | Description |
|---|---|
invoice.created | Invoice was created |
invoice.sent | Invoice was emailed to customer |
invoice.paid | Customer paid the invoice |
invoice.voided | Invoice was voided |
Methods reference
| Method | Description |
|---|---|
create(params) | Create a new invoice |
retrieve(id) | Retrieve an invoice by ID |
list(params?) | List invoices with optional filters |
open(id) | Transition from DRAFT to OPEN |
send(id) | Send the invoice via email |
void(id) | Void an unpaid invoice |
TypeScript types
Response body reference
All responses are wrapped in { success: true, data: ... }. The fields below describe what's inside data.
create() response
Invoice (create)
idstringUnique invoice ID (UUID)appIdstringYour app IDcustomerAccountIdstringCustomer being billedsubscriptionIdstring | nullLinked subscription, if auto-generatedpaymentIntentIdnullAlways null at creation (set when paid)invoiceNumberstringSequential number, e.g. "INV-00001"statusstring"DRAFT" at creationsubtotalstringPre-tax total (Decimal as string)taxAmountstringTax portion (Decimal as string)totalstringFinal total including taxcurrencystringCurrency code, default "USD"taxRateIdstring | nullApplied tax rate IDdueDatestring | nullISO 8601 due datepaidAtnullSet when invoice is paidvoidedAtnullSet when invoice is voidedperiodStartstring | nullBilling period start (subscriptions)periodEndstring | nullBilling period end (subscriptions)allowedChainsstring | number[]"ALL" or array of chain IDsallowedTokensstring | string[]"ALL" or array of token keysmemostring | nullNote to customermetadataobjectYour metadata key-value pairscreatedAtstringISO 8601 creation timestampupdatedAtstringISO 8601 last update timestampitemsInvoiceItem[]Line items (see below)customerAccountCustomerAccountFull customer objecttaxRateTaxRate | nullFull tax rate object, if appliedInvoiceItem (nested in items[])
idstringItem ID (UUID)invoiceIdstringParent invoice IDproductPlanIdstring | nullLinked product planproductPlanPriceIdstring | nullLinked pricetaxRateIdstring | nullItem-level tax ratedescriptionstringItem descriptionamountstringItem amount (Decimal as string)currencystringItem currencyquantitynumberItem quantitytaxAmountstringTax for this itemcreatedAtstringISO 8601 timestampretrieve() response
Returns all fields from create() above, plus these additional nested objects:
Additional fields on retrieve
appAppFull app object (id, name, environment, etc.)paymentIntentPaymentIntent | nullFull payment intent with nested transactions[], once paiditems[].taxRateTaxRate | nullTax rate on each individual itemretrieve() includes transactions
paymentIntent on retrieve also includes its transactions[] array, so you can see all on-chain tx hashes, statuses, and block numbers.list() response
Same as retrieve() but without the app relation. Includes items (with nested taxRate),customerAccount, taxRate, and paymentIntent (with transactions).
open() and void() response
Both return the invoice with items[] only (no customer, no tax rate, no payment intent). The status will be "OPEN" or "VOID" respectively.
send() response
Returns a simple confirmation: