How to take a deposit and collect the remaining balance on Stripe

Stripe has three routes. Invoice payment plans split one invoice into a deposit and later installments; they are in private preview, work only on invoices sent for the customer to pay, and don't charge saved payment details automatically. Invoice partial payments let you attach extra payments to an open invoice, or let the customer pay a custom amount on the hosted invoice page once you turn that on. For a deposit at checkout, you charge it with Checkout, save the card, and charge the balance off-session from a job of your own.
Verified against official documentationReviewed Send a correction (opens in a new tab)

The short answer on Flint

A Flint invoice takes a payment schedule: a deposit due when you issue it and the balance on the due date, or up to 14 installments, by percentage, fixed amount, or whatever remains. The buyer pays each one from the same hosted invoice link, or, with automatic collection, Flint charges their saved card on each due date. Reminders and late fees run per installment, and the deposit, the balance, and any refund stay on one order. Card processing runs on Stripe underneath. The Flint request is below.

What Stripe offers for deposits

Invoice payment plans are the closest match. A plan divides one invoice into installments with their own due dates, such as a fixed-amount deposit followed by the rest, and Stripe sends a reminder for each. Stripe lists these limits:

  • The feature is in private preview, requested through a form, with a preview API version.
  • Plans don't auto-charge customers with saved payment details; customers return to the payment page for each later payment, and charge_automatically invoices can't use them.
  • They can't be applied to subscription invoices.
  • On Connect, application fees can't be set on a payment plan invoice.

Partial payments work on open invoices, except subscription invoices that Stripe charges automatically, which are in private preview: you attach a separate PaymentIntent for any amount up to what remains, or enable partial payments in your invoice settings so the customer can type an amount on the hosted invoice page. The customer chooses that amount, so it doesn't enforce a deposit.

Outside invoices, Stripe's guide to saving payment details lists charging a deposit and saving the card to charge the full amount later as a use case. The deposit is a Checkout payment; the balance is a PaymentIntent your server creates later with off_session.

The checkout deposit, in code

Charge the deposit and keep the card:

JavaScript
// 1. Charge the 25% deposit in Checkout and save the card for the balance
const session = await stripe.checkout.sessions.create({
  mode: "payment",
  customer: booking.stripeCustomerId,
  line_items: [{
    price_data: {
      currency: "usd",
      unit_amount: Math.round(booking.totalCents * 0.25),
      product_data: { name: `Deposit: ${booking.title}` },
    },
    quantity: 1,
  }],
  payment_intent_data: { setup_future_usage: "off_session" },
  metadata: { booking_id: booking.id, part: "deposit" },
  success_url: "https://example.com/booked?session_id={CHECKOUT_SESSION_ID}",
});

Then a job of yours charges the balance. Stripe's docs warn that when the conditions for an authentication exemption aren't met, an off-session PaymentIntent can throw an error, so the job needs a path back to the customer:

JavaScript
// 2. Your daily job charges the balance on the job date
for (const booking of await db.bookings.balanceDue(today())) {
  const balance = booking.totalCents - booking.paidCents; // recomputed from your records
  try {
    await stripe.paymentIntents.create(
      {
        amount: balance,
        currency: "usd",
        customer: booking.stripeCustomerId,
        payment_method: booking.savedPaymentMethodId,
        off_session: true,
        confirm: true,
        metadata: { booking_id: booking.id, part: "balance" },
      },
      { idempotencyKey: `balance-${booking.id}-${booking.balanceAttempt}` },
    );
  } catch (err) {
    // Declined, or the bank wants authentication the customer can't give
    // off-session. Email a link to pay on session, and retry on your schedule.
    await db.bookings.markBalanceFailed(booking.id, err.code);
    await sendPayBalanceEmail(booking);
  }
}

That is a bookings table with totals and payments, a scheduler, an email, a page where the customer pays the balance on session, and your own terms and consent for charging a saved card. These are the places it goes wrong:

Where hand-built deposits go wrong

  1. The balance charge fails and the customer is gone#

    The job is done, the card on file declined, and nobody told the customer.

    An off-session charge can decline, and when a bank asks for authentication and the exemption conditions aren't met, the PaymentIntent errors. The customer isn't in your checkout to respond, so the balance waits on an email you write and a page you build.

    Confirm it

    List PaymentIntents your balance job created that ended in requires_payment_method or requires_action.

    Fix

    Send the customer a link to pay the balance on session, retry on a schedule you choose, and stop the job once they pay by other means.

  2. The deposit and the balance don't know about each other#

    Finance can't tell which deposits still have a balance due.

    The deposit is one PaymentIntent and the balance is another. Outside an invoice, nothing in Stripe says the second belongs to the first, or how much is still owed.

    Confirm it

    Count bookings with a succeeded deposit and no balance payment past the job date.

    Fix

    Keep the booking, its total, and both payment IDs in your own table, and drive the balance job from it rather than from Stripe.

  3. The job changes after the deposit#

    The customer added a second room, and the balance charge used the original quote.

    The deposit was computed from the quote at booking. A change to the work changes the balance, and the amount your job charges is whatever your database says when it runs.

    Confirm it

    Compare each balance charge with the final quote for the job.

    Fix

    Recompute the balance from the current quote immediately before charging, and tell the customer the new amount first.

  4. Cancellations refund the wrong payment#

    A cancellation refunded the balance payment in full and kept the deposit as a fee, the opposite of the policy.

    A refund belongs to one PaymentIntent. Your cancellation policy, such as a nonrefundable deposit or a fee, is code that has to pick the right payment and amount.

    Confirm it

    Review refunds on bookings that had both a deposit and a balance payment.

    Fix

    Write the policy as a function over both payments, and record the refund against the booking as well as the PaymentIntent.

On Flint, the deposit is an entry on the invoice

One request creates the invoice, its order, and a schedule of 25% when it is issued and the rest by December 15:

cURL
curl -X POST https://api.withflintpay.com/v1/invoices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: invoice-kitchen-remodel-001" \
  -H "Content-Type: application/json" \
  -d '{
    "quick_pay": {
      "customer_id": "cus_1kmn0aExample",
      "line_items": [{
        "name": "Kitchen remodel, phase 1",
        "quantity": 1,
        "unit_price_money": { "amount": 480000, "currency": "USD" },
        "fulfillment": { "requirement": "none" }
      }]
    },
    "payment_due": { "type": "absolute", "due_at": "2026-12-15T23:59:59Z" },
    "collection": { "mode": "buyer_initiated" },
    "schedule_entries": [
      {
        "kind": "deposit",
        "amount_specification": { "type": "percentage", "percent": 25 },
        "due": { "type": "at_issue" }
      },
      {
        "kind": "balance",
        "amount_specification": { "type": "remaining_balance" },
        "due": { "type": "invoice_due_date" }
      }
    ],
    "recipient_email": "homeowner@example.com"
  }'

Issue it, and the buyer gets one link that shows the deposit due now and the balance due later. To charge a saved card instead, set automatic collection; Flint charges the card right after issue for the deposit and on the balance's due date, retries on your retry policy, and still lets the buyer pay with another card from the hosted invoice:

JSON
"collection": {
  "mode": "automatic",
  "payment_method_id": "pm_1kmn0aExample"
}

What each part does:

  • Entries. kind is deposit, installment, or balance. Amounts are a percentage, a fixed amount_money, or the remaining_balance. Due dates are at_issue, a date, or the invoice_due_date. Up to 14 entries.
  • Follow-up. Reminders run on your schedule for each installment, and a late fee on the payment terms is assessed once per overdue installment.
  • One record. The invoice owns one order, so the deposit, the balance, a check you record by hand, and any refund all read from it, and outstanding_money says what is still owed.
  • Tips. If the order has a tip, the deposit collects it first.

One limit to plan around: an invoice that uses Flint's automatic tax takes one payment for the full balance, so issuing a deposit schedule on it returns AUTOMATIC_TAX_INVOICE_INSTALLMENTS_UNSUPPORTED. For a taxed job paid in parts, send the tax yourself as external tax.

To take a deposit before a booking instead of billing one, a payment link works, and Collect deposits with payment links walks through that workflow. That puts the deposit and the balance on two orders; the invoice schedule above keeps them on one. The choice between the three tools is in Payment links, checkout sessions, or invoices?

Who Flint is built for

US businesses billing customers in USD for work booked ahead: contractors, event and venue businesses, studios, agencies, and the software built for them. See Flint invoices. Invoices are an add-on at 0.40% of the payments collected through them, with no monthly fee.

Stripe and Flint for a deposit and balance

Stripe invoice payment plansStripe Checkout and a saved cardFlint invoice schedule
AvailabilityPrivate previewAvailableAvailable
Charges the saved card on the due dateNo; the customer returns to payYour job, off-sessionYes, with collection.mode: "automatic"
Customer pays from one linkYesYour page for the balanceYes
Reminders per installmentYesYour emailsYes
Late fee per overdue installmentNot describedYour codeOn the payment terms
What tracks the balanceThe invoiceYour databaseThe invoice and its order's outstanding_money

Questions, answered

Can Stripe take a deposit and charge the remaining balance later?

Yes, in three ways. Invoice payment plans split one invoice into a deposit and later installments, in private preview, for invoices sent to the customer to pay. Invoices also accept partial payments, attached through the API or entered on the hosted invoice page once you enable it. Or you charge the deposit with Checkout, save the card, and charge the balance off-session from a job of your own.

Do Stripe invoice payment plans charge the saved card automatically?

No. Stripe's docs say payment plans don't auto-charge customers with saved payment details, and customers return to the payment page for each later payment. They can't be used with charge_automatically invoices or on subscription invoices.

How do I create a deposit invoice?

On Flint, create an invoice with schedule_entries: a deposit due at issue, as a percentage or a fixed amount, and a balance for the remaining amount due on the invoice due date. The buyer pays each from the same hosted invoice link, or Flint charges their saved card on each due date when collection is automatic.

Can I take a deposit with a payment link?

Yes. A payment link collects the deposit before the work starts, and you bill the balance later with an invoice. On Flint that makes two orders; an invoice with a payment schedule keeps the deposit and the balance on one.

Does Flint calculate sales tax on a deposit invoice?

Not automatically. An invoice that uses Flint's automatic tax takes one payment for the full balance, so a deposit schedule needs tax you supply as external tax, or no tax. Invoices paid in one payment can use automatic tax.

Is Flint a good alternative to Stripe for deposits and payment plans?

Yes, for US businesses billing in USD that want a deposit and balance on one invoice, charged automatically to a saved card or paid from one link, with reminders and late fees per installment. Invoices are an add-on at 0.40% of payments collected through them, on top of Flint's card rate of 3.79% + 35¢, which covers Stripe's processing fees, with no monthly fee.

Sources

All sources accessed October 15, 2026.