Pending invoice items

Add one-off charges to a subscription and collect them at renewal or on demand.

View as Markdown

Pending invoice items (also called floating items) let you add one-off charges to a subscription. By default, these charges are collected on the next renewal invoice. You can also bill them immediately without waiting for renewal. This is useful for usage-based charges, setup fees, or any ad-hoc billing.

How it works

When you create an invoice item with a subscription_id, the item is stored as a “floating” item:

  1. The item is created with invoice_id = null (not yet attached to an invoice)
  2. The item is linked to the subscription via subscription_id
  3. At the next renewal, PaymentKit automatically sweeps all floating items into the renewal invoice
  4. The customer is charged for the subscription’s recurring items plus all pending one-off charges

Create a pending invoice item

Add a one-off charge to a subscription using the invoice items endpoint.

With a catalog price

Use a catalog price when you want consistent product naming and reporting:

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoice-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-d '{
> "customer_id": "cus_abc123",
> "subscription_id": "sub_xyz789",
> "price_id": "price_sms_usage",
> "quantity": 150,
> "description": "SMS charges - July 2026 (150 messages)"
>}'

With a custom amount

Create an amount-only item when you don’t need a catalog price. The currency is automatically derived from the subscription:

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoice-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-d '{
> "customer_id": "cus_abc123",
> "subscription_id": "sub_xyz789",
> "amount": 75.00,
> "description": "Custom setup fee"
>}'

Currency handling: When creating an amount-only item (no price_id), the currency is automatically set to match the subscription’s currency. When using a price_id, the price’s currency must match the subscription’s currency.

View pending charges

Preview the upcoming invoice

Use the subscription preview endpoint to see all pending charges that will be collected at renewal:

$curl -X GET https://app.paymentkit.com/api/{account_id}/subscriptions/{subscription_id}/preview \
>-H "Authorization: Bearer sk_live_..."

Each pending (floating) item is returned as its own line item in the upcoming_invoice.items array, listed alongside the subscription’s recurring items — so you can see exactly what will be charged, not just the aggregate total. Every pending item includes its description, quantity, and amount, is denominated in the subscription’s currency, and carries a proration flag indicating whether it was generated by a mid-cycle change.

Itemizing pending charges in the preview does not change any totals: upcoming_invoice.subtotal, total, and related amounts already account for these items exactly once.

1{
2 "upcoming_invoice": {
3 "items": [
4 {
5 "description": "Pro plan",
6 "quantity": 1,
7 "amount": 4900,
8 "currency": "usd",
9 "proration": false
10 },
11 {
12 "description": "SMS charges - July 2026 (150 messages)",
13 "quantity": 150,
14 "amount": 1500,
15 "currency": "usd",
16 "proration": false
17 }
18 ]
19 }
20}

List pending items for a subscription

Use the invoice items list endpoint with status=floating to get all pending (unbilled) charges for a subscription. Floating items are those not yet swept onto an invoice:

$curl -X GET "https://app.paymentkit.com/api/{account_id}/invoice-items?subscription_id=sub_xyz789&status=floating" \
>-H "Authorization: Bearer sk_live_..."

The response is paginated — matching items are returned in the items array alongside total and has_more. You can also filter by customer_id, or pass status=attached to list items already swept onto an invoice. Omit status to return both.

Global search now indexes invoice items. Paste an item’s ii_ id into the dashboard search bar (or scope a search with the ii prefix) to jump straight to a pending item.

Validation rules

RuleDescription
Subscription stateMust be active or trialing. Cannot add pending items to cancelled, paused, or past_due subscriptions.
Customer matchThe customer_id must match the subscription’s customer.
Currency matchIf price_id is provided, the price’s currency must match the subscription’s currency.
Positive amountAmount-only items (no price_id) must have a positive amount or unit_amount.

Renewal behavior

When a subscription renews:

  1. PaymentKit creates a draft renewal invoice
  2. All floating items for the subscription are attached to this invoice
  3. The invoice is finalized and payment is collected
  4. The floating items now have invoice_id set to the renewal invoice

If the renewal invoice is voided (e.g., due to mid-cycle changes), floating items return to their unbilled state (invoice_id = null) and will be swept into the replacement invoice.

Bill pending items on demand

Bill accumulated charges immediately without waiting for the next renewal. The bill-pending-items endpoint sweeps all floating items for a customer into standalone invoices, finalizes them, and attempts collection.

Create an off-cycle invoice

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoices/bill-pending-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-H "Idempotency-Key: bill-cus123-july-usage" \
>-d '{
> "customer_id": "cus_abc123"
>}'

Response:

1{
2 "invoices": [
3 {
4 "id": "inv_abc123",
5 "currency": "usd",
6 "status": "paid",
7 "total_amount_atom": 1500,
8 "items_swept": 3
9 }
10 ]
11}

The response contains one invoice per currency. If the customer has no pending items, the invoices array is empty.

Filter which items to bill

By default, all floating items for the customer are swept. Use filters to narrow the scope.

Bill specific items

Pass item_ids to sweep only specific floating items:

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoices/bill-pending-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-d '{
> "customer_id": "cus_abc123",
> "item_ids": ["ii_item1", "ii_item2"]
>}'

When item_ids is provided, other filters (subscription_id, currency) are ignored.

Bill items from a specific subscription

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoices/bill-pending-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-d '{
> "customer_id": "cus_abc123",
> "subscription_id": "sub_xyz789"
>}'

Bill items in a specific currency

$curl -X POST https://app.paymentkit.com/api/{account_id}/invoices/bill-pending-items \
>-H "Authorization: Bearer sk_live_..." \
>-H "Content-Type: application/json" \
>-d '{
> "customer_id": "cus_abc123",
> "currency": "EUR"
>}'

Request fields

FieldTypeRequiredDescription
customer_idstringYesCustomer whose pending items to bill
item_idsarrayNoSpecific item IDs to sweep. Overrides other filters.
subscription_idstringNoNarrow to a single subscription
currencystringNoNarrow to a single currency. If omitted, creates one invoice per currency.
tax_amount_atomintegerNoTax amount in smallest currency unit (default: 0)
discount_idstringNoDiscount to apply to the invoice
collection_methodstringNocharge_automatically or send_invoice. Defaults to customer’s setting.
descriptionstringNoInvoice memo

Response fields

FieldTypeDescription
invoicesarrayInvoices created (one per currency)
invoices[].idstringInvoice external ID
invoices[].currencystringInvoice currency code
invoices[].statusstringpaid, open, etc.
invoices[].total_amount_atomintegerTotal in smallest currency unit
invoices[].items_sweptintegerNumber of floating items attached

Behavior

ScenarioBehavior
Multi-currencyCreates one invoice per currency. A customer with USD and EUR pending items gets two invoices.
Payment successInvoice status is paid.
Payment failureInvoice remains open and enters the dunning flow.
No pending itemsReturns empty invoices array (200 OK).
Paused subscriptionsItems from paused subscriptions are excluded.
Race with renewalRow-level locking prevents double-billing. If a renewal is in progress, returns 409 Conflict.

Idempotency: Without an Idempotency-Key header, duplicate requests create duplicate invoices. Always include an idempotency key for production use.

Use cases

Use caseImplementation
Usage-based billingTrack usage throughout the billing period, then create a pending item with the total usage before renewal
One-time setup feesAdd a setup fee when the subscription is created or upgraded
Ad-hoc professional servicesBill consulting or implementation hours as they occur
Overage chargesAdd charges when customers exceed plan limits
On-demand usage billingAccumulate charges mid-cycle (e.g., SMS), then call /invoices/bill-pending-items to collect immediately

Pending items do not affect subscription state. Pending charges are passive — they don’t trigger pause, cancel, or dunning logic. They are simply swept into the renewal invoice when it’s created.