Create an Invoice
Send a payment link to a customer so they can pay their booking balance online through Stripe.
Invoices in Resytech are payment links tied to a booking. When you create an invoice, the customer receives an email with a link to a payment page where they can enter their card details and pay. The payment is processed through Stripe and automatically updates the booking balance.
Prerequisites
- A booking with an outstanding balance greater than $0.00.
- The booking must not be canceled.
- A connected Stripe account (see Set Up Stripe).
- The customer must have a valid email address on file.
Create an Invoice
- Open the booking from Dashboard > Bookings.
- Click Send Invoice (or navigate to the invoice section of the booking).
- Configure the invoice:
| Field | Required | Description |
|---|---|---|
| Amount | Yes | The amount to charge, in cents internally but displayed in dollars. This can be the full balance or a partial amount (e.g., a deposit). |
| Confirm on Pay | No | When enabled, the booking status automatically changes to Confirmed when the customer pays. Useful for draft or pending bookings where payment confirms the reservation. |
| Send To Email Override | No | If set, the invoice email is sent to this address instead of the customer's primary email. Useful when billing a different party. |
| Send Type | Yes | How the invoice notification is delivered (email or SMS). |
- Click Send.
The system creates the invoice with a status of Open and generates a unique token for the payment link. The customer receives a notification with the link.
Invoice Statuses
| Status | Meaning |
|---|---|
| Open | Invoice has been sent and is awaiting payment |
| Paid | Customer has successfully paid the invoice |
| Closed | Invoice was manually closed without payment |
How the Customer Pays
When the customer clicks the payment link:
- They see a summary of their booking and the amount due.
- They enter their card details using Stripe Elements (a secure, PCI-compliant payment form).
- If the card requires 3D Secure authentication, they are prompted to complete it.
- On success, they see a confirmation with their booking confirmation code.
The payment page validates several things before allowing payment:
- The invoice is still open.
- The booking is not canceled.
- The booking still has an outstanding balance.
- The booking's time slot is still available (for draft bookings).
- Any required agreements/waivers have been acknowledged.
What Happens After Payment
When the invoice is paid:
- The invoice status changes to Paid.
- A
CustomerPaymentrecord is created with the Stripe PaymentIntent ID. - The booking balance is reduced by the paid amount.
- If Confirm on Pay was enabled and the booking was in draft/pending status, the booking status changes to Confirmed and a confirmation email is sent.
- Calendar sync is triggered if Google Calendar integration is active.
Resend an Invoice
If the customer did not receive the invoice or needs a reminder:
- Open the booking.
- Navigate to the invoice section.
- Click Resend on the open invoice.
This sends a fresh notification with the same payment link.
Race Condition Protection
The invoice payment system includes safeguards against duplicate payments:
- Row-level locking: When a customer submits payment, the invoice row is locked at the database level to prevent concurrent modifications.
- Pending payment detection: If a payment is already in progress (e.g., the customer has a 3D Secure prompt open), a second payment attempt is blocked with the message "A payment is already being processed for this invoice."
- Idempotency keys: Each payment attempt includes a unique idempotency key sent to Stripe, preventing duplicate charges on retries.
- Stale payment cleanup: If a previous payment attempt failed or was canceled, the system automatically clears the stale reference and allows a new attempt.
3D Secure (3DS) Flow
Some cards require 3D Secure authentication. When this happens:
- The initial payment returns a
requires_actionstatus. - The PaymentIntent ID is stored on the invoice to prevent concurrent attempts.
- The customer completes 3DS in their browser (e.g., entering a code from their bank's app).
- On success, the payment is retried with the authenticated PaymentIntent.
- The invoice is marked as paid and the balance is updated.
If the customer abandons the 3DS flow, the PaymentIntent eventually transitions to canceled or requires_payment_method. The next time the customer visits the payment link, the stale PaymentIntent is cleared and they can start a fresh payment.
Tips
- Set the amount carefully. The invoice amount is fixed when created. If you need to change the amount, close the existing invoice and create a new one.
- Use Confirm on Pay for pending bookings. This eliminates the need to manually confirm bookings after the customer pays their deposit or full balance.
- The email override field is useful for group bookings where a corporate contact pays on behalf of the participants.
- Invoice payments create the same payment records as dashboard card payments. They appear identically in reports and the booking's payment history.
What to Do Next
- Process a Payment -- add a payment directly from the dashboard instead of sending an invoice.
- Set Up Auto-Expire -- automatically cancel bookings if the invoice is not paid by a deadline.
