*** title: Create an invoice subtitle: >- Generate one-off invoices for custom charges, or understand how subscription invoices are created automatically. ----------------------------------- # One-off invoices Create a standalone invoice for a customer that is not tied to a subscription. Use one-off invoices for custom charges, consulting fees, setup fees, or any non-recurring billing. 1. Go to **Billing > Invoices** in the sidebar 2. Click **Create Invoice** 3. Select a customer 4. Set the currency and issued date 5. Add line items with descriptions, quantities, and amounts 6. Click **Create** The invoice is created in **Draft** state. Finalize it to begin collection. ```bash curl -X POST https://api.paymentkit.com/api/{account_id}/invoices \ -H "Authorization: Bearer sk_live_..." \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cus_abc123", "currency": "USD", "issued_at": "2026-02-01T00:00:00Z", "description": "Setup fee - Enterprise onboarding", "items": [ { "description": "Enterprise onboarding", "quantity": 1, "amount": 500.00 }, { "description": "Custom integration development", "quantity": 4, "unit_amount": 150.00 } ] }' ``` ```python invoice = client.invoices.create( account_id="acc_abc123", customer_id="cus_abc123", currency="USD", issued_at="2026-02-01T00:00:00Z", description="Setup fee - Enterprise onboarding", items=[ { "description": "Enterprise onboarding", "quantity": 1, "amount": 500.00 }, { "description": "Custom integration development", "quantity": 4, "unit_amount": 150.00 } ] ) ``` ## Line item fields | Field | Description | | ------------- | ------------------------------------------------------------------------- | | `name` | Display name for the line item | | `description` | Description displayed on the invoice | | `quantity` | Number of units (default: 1) | | `unit_amount` | Price per unit | | `amount` | Total amount for this line item (alternative to `unit_amount * quantity`) | | `price_id` | Link to an existing price in your product catalog | | `metadata` | Free-form metadata for the item | Use `price_id` to reference a catalog price, or provide `amount`/`unit_amount` for ad-hoc charges. # Subscription invoices Subscription invoices are generated automatically by the billing lifecycle. You do not need to create them manually. PaymentKit generates invoices at these points: | Event | Billing reason | | ------------------------------------------------------------ | --------------------- | | Subscription created | `subscription_create` | | Billing period renews | `subscription_cycle` | | Subscription items changed (with `always_invoice` proration) | `subscription_update` | Each invoice contains line items built from the subscription's active items at the time of generation. # Invoice lifecycle Every invoice follows this state flow: | State | Description | | ------------------ | ------------------------------------------------------------------- | | **Draft** | Invoice is being prepared. Items and amounts can still be modified. | | **Open** | Finalized and ready for payment. Amounts are locked. | | **Paid** | Payment collected in full. | | **Partially paid** | Some payment received, balance remaining. | | **Past due** | Payment deadline has passed. Dunning retries are active. | | **Void** | Invoice cancelled. No payment expected. | | **Uncollectible** | All collection attempts exhausted. | ## Transitions | From | To | Trigger | | -------------- | -------------- | -------------------------------- | | Draft | Open | Invoice finalized | | Draft | Void | Invoice voided before finalizing | | Open | Paid | Payment succeeds in full | | Open | Partially paid | Partial payment received | | Open | Past due | Payment deadline passes | | Open | Void | Invoice voided | | Open | Uncollectible | Dunning exhausted | | Partially paid | Paid | Remaining balance paid | | Partially paid | Past due | Payment deadline passes | | Partially paid | Void | Invoice voided | | Past due | Paid | Payment recovered | | Past due | Partially paid | Partial payment received | | Past due | Uncollectible | Dunning exhausted | | Uncollectible | Void | Invoice voided | # Finalize an invoice Finalizing moves a draft invoice to **Open** state, locks all amounts, and optionally triggers PDF generation and email delivery. ```bash curl -X POST https://api.paymentkit.com/api/{account_id}/invoices/{invoice_id}/finalize \ -H "Authorization: Bearer sk_live_..." ``` ```python invoice = client.invoices.finalize( account_id="acc_abc123", invoice_id="in_abc123" ) ``` # Collect payment Attempt to collect payment on an open invoice: ```bash curl -X POST https://api.paymentkit.com/api/{account_id}/invoices/{invoice_id}/collect \ -H "Authorization: Bearer sk_live_..." ``` The response includes the payment outcome: ```json { "invoice_id": "in_abc123", "invoice_status": "paid", "subscription_id": null, "payment_status": "paid", "error_message": null } ``` If the invoice is still in **Draft** state, the collect endpoint finalizes it before attempting payment. For subscription invoices, payment collection is handled automatically by the lifecycle engine. Use the collect endpoint for manual invoices or to retry a failed payment. # Webhook events | Event | Trigger | | ------------------------------ | ---------------------------- | | `invoice.created` | Invoice created | | `invoice.finalized` | Draft finalized to Open | | `invoice.paid` | Payment collected in full | | `invoice.payment_succeeded` | A payment attempt succeeded | | `invoice.payment_failed` | A payment attempt failed | | `invoice.overdue` | Invoice became past due | | `invoice.voided` | Invoice voided | | `invoice.marked_uncollectible` | Invoice marked uncollectible |