---
title: Payments
description: Record and track payments in Easy Invoice — manual entries, gateway-driven payments, partial payments, refunds, and the relationship between Payment posts and invoices.
---
# Payments
Every payment in Easy Invoice is its own post (`easy_invoice_payment` CPT). The invoice's payment status is **derived** from the related Payment records — that's how partial payments, refunds, and split payments work without breaking the invoice.
## What a payment _is_
- **Custom post type**: `easy_invoice_payment` (`includes/EasyInvoice.php:349–377`).
- **Public**: no.
- **Admin UI**: hidden submenu — visible from Easy Invoice → Payments.
Each Payment links to **one** invoice via post meta. An invoice can have **many** payment records (partial flows, refunds, split methods).
## Recording a manual payment
Open Easy Invoice → Add New Payment.
- Pick the invoice from the dropdown (search by invoice number).
- Set the Payment date (defaults to today).
- Pick the Gateway — usually Manual for cash / wire / cheque.
- Enter the Amount (full or partial).
- Add a Transaction ID (optional reference).
- Pick a Status: Completed for normal, Pending while you wait on bank clearance, Refunded after issuing a refund.
- Click Save.
Easy Invoice then:
1. Sums all completed payments for the invoice.
2. Compares against the invoice total.
3. Updates the invoice's `_payment_status` meta:
- **completed** — sum ≥ total.
- **partial-paid** — `0 < sum < total` (Pro shows partial).
- **unpaid** — sum is zero.
4. Fires `easy_invoice_payment_completed` (action) for completed payments.
> The decision logic lives in `PaymentController::should_update_invoice_status` (`includes/Controllers/PaymentController.php:1219`) and respects the `easy_invoice_should_update_invoice_status` filter.
## Gateway-driven payments
When a client pays via a configured gateway, Easy Invoice creates the Payment record automatically.
| Gateway | When it creates | Webhook endpoint |
| --- | --- | --- |
| **PayPal** (Free) | After PayPal IPN returns success. | n/a (IPN handler) |
| **Manual** (Free) | Never — admin creates manually. | n/a |
| **Stripe** PRO | After Stripe webhook fires `payment_intent.succeeded`. | `admin-ajax.php?action=easy_invoice_stripe_webhook` |
| **Square** PRO | After Square webhook + 15-min reconcile cron. | `admin-ajax.php?action=easy_invoice_square_webhook` |
| **Mollie** PRO | After Mollie webhook returns paid. | `admin-ajax.php?action=easy_invoice_mollie_webhook` |
| **Authorize.Net** PRO | After Authorize.Net post returns. | `admin-ajax.php?action=easy_invoice_authorizenet_response` |
| **Bank Transfer** PRO | Created in `pending-bank` status; admin marks completed. | n/a |
| **Cheque** PRO | Created in `pending-cheque`; admin marks completed. | n/a |
| **Cash** PRO | On client click; mark completed manually after collection. | n/a |
| **Moneris** PRO | After Moneris response. | n/a |
> For full webhook setup, see [Payment gateways](/payment-settings).
## Partial payments
PRO
Partial payments module
Pro lets clients pay any amount toward an invoice. The remaining balance stays open and can be paid later via the same public link.
Unlock partials →
How it works:
1. Enable under Settings → Partial Payments (Pro only).
2. Set a **minimum** partial (e.g. 25 % of total).
3. The public invoice page shows an editable amount field.
4. Each partial creates a Payment record — invoice status reflects "partial-paid".
5. When the sum reaches the total, status flips to "completed" automatically.
The `easy_invoice_display_total` filter (`PartialPayments.php:22`) lets templates show paid vs balance side by side.
## Deposit invoices
PRO
Deposit invoices module
Charge a deposit (e.g. 50% upfront) and bill the balance later as a follow-up invoice. Each deposit is its own Payment record linked to the parent invoice.
Unlock deposits →
Two flows are supported:
- **Single deposit + balance** — charge X % now, the remainder when work is done.
- **Multi-stage** — charge a series of percentages (e.g. 30 / 40 / 30).
Set up under Settings → Deposit Invoices.
## Refunds
A refund is a **status change** on the Payment record:
- Issue the refund in the gateway dashboard (Stripe, PayPal, etc.).
- Open Easy Invoice → Payments → find the payment.
- Edit → set Status to Refunded.
- Save.
The invoice's `_payment_status` recomputes — if the only successful payment was refunded, the invoice goes back to **unpaid**. If you partially refunded, status reflects the new sum (e.g. `partial-paid`).
> Stripe refunds via the gateway dashboard don't auto-mirror back to Easy Invoice. Plan for the two-step manual mirror.
## Payment reminders
### Free: bank / cheque pending reminder
Cron `easy_invoice_payment_reminder` runs **daily** and emails clients who have payments stuck in `pending-bank` or `pending-cheque` for more than N days. Configure under Settings → Advanced → Payment reminder days.
### Pro: full reminder engine
PRO
Payment reminder cadence
Send N days before due, on due day, and X days after due. Independent templates and frequencies for each.
Unlock reminders →
Pro cron `easy_invoice_send_payment_reminders` runs daily — see Settings → Email → Payment Reminder.
## Receipts
When a payment completes, Easy Invoice can email a receipt:
- **Free**: configure under Settings → Email → Payment Received.
- **Pro**: receipts are also stored as separate documents (action `easy_invoice_pro_receipt_generated` — `ReceiptController.php:273`) and can be downloaded individually.
## Reports tied to payments
Open Easy Invoice → Reports for:
- **Revenue over time** (line chart).
- **Status breakdown** (paid vs unpaid vs overdue).
- **Payment-method mix** (which gateway brings the most money).
- **Top clients** (by total paid).
All charts are Chart.js, rendered client-side.
## Where to go next
- 💳 [Payment gateways](/payment-settings) — connect Stripe, PayPal, Square.
- 🧾 [Invoices](/invoices) — invoice statuses and how they react to payments.
- 🔁 [Recurring & subscriptions](/recurring-invoices) — schedule repeating bills.
- 💎 [Pro features overview](/third-party-integrations) — partials, deposits, reminders.