Payments
Payment proofs
How clients report a payment with \"I have paid\", and how you accept or reject their proof.
When a client pays by bank transfer or a local QR code, the money moves outside our system. A payment proof is how the client tells you they have paid: they click I have paid on the pay page, enter what they paid, and can upload a receipt or screenshot. You review it, check your account, and then accept it (which records the payment) or reject it. A proof never marks an invoice paid on its own.
How proofs work
- On the pay page of an invoice that accepts an instruction rail (bank transfer, or from the week of 25 January 2027 a local QR rail), the client clicks I have paid.
- They can enter:
- the amount they paid,
- the date they paid,
- a short note,
- a proof file (PDF, PNG or JPEG).
- A proof is created with the status
pending, and the business is notified. - A member with
payments.recordreviews it:- Accept: a payment is recorded from the proof, the invoice balance goes down, and the invoice moves to paid or partially paid. The proof becomes
acceptedand is linked to the payment. - Reject: nothing is recorded. The proof becomes
rejected.
- Accept: a payment is recorded from the proof, the invoice balance goes down, and the invoice moves to paid or partially paid. The proof becomes
- Who reviewed the proof, and when, is stored with it and in the audit log.
"I have paid" is a claim, not a payment. Anyone with the pay link could submit a proof, and a screenshot can be edited. Always check that the money arrived in your account before you accept.
Proof statuses
| Status | Meaning |
|---|---|
pending | Submitted by the client, waiting for your review |
accepted | You confirmed it; a payment was recorded and linked |
rejected | You declined it; no payment was recorded |
Review proofs in the app
Open Payments
In the sidebar, open Payments under Get paid. Pending proofs are listed with the invoice, client, claimed amount and date.
Open the proof
Look at the client's note and open the uploaded file. Files are stored privately and opened through short-lived links.
Check your account
Find the transfer in your bank or wallet. Compare the amount, date and reference.
Accept or reject
Accept to record the payment. Reject if you cannot find the money. If a different amount arrived than the client claimed, record the payment for the amount that actually arrived.
Through the API
| Action | REST | Permission |
|---|---|---|
| List payment proofs | GET /v1/payment-proofs | payments.view |
| Accept a payment proof | POST /v1/payment-proofs/{id}/accept | payments.record |
| Reject a payment proof | POST /v1/payment-proofs/{id}/reject | payments.record |
| Submit a proof (pay page) | POST /v1/public/pay/{token}/proofs | pay token |
| Upload a proof file (pay page) | POST /v1/public/pay/{token}/uploads | pay token |
curl "https://api.freeinvoiceautomation.com/v1/payment-proofs?status=pending" \
-H "Authorization: Bearer $FIA_API_KEY"{
"data": [
{
"id": "0193f2d0-7a8b-7c9d-8e0f-1a2b3c4d5e70",
"document_id": "0193f2b4-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"client_id": "0193f2a1-0c11-7d2e-9a40-1b2c3d4e5f60",
"claimed_amount_minor": "120000",
"currency": "EUR",
"claimed_paid_on": "2027-01-17",
"client_note": "Paid from our main account, ref 7781-2201",
"status": "pending",
"payment_id": null
}
],
"next_cursor": null,
"has_more": false
}curl -X POST "https://api.freeinvoiceautomation.com/v1/payment-proofs/0193f2d0-7a8b-7c9d-8e0f-1a2b3c4d5e70/accept" \
-H "Authorization: Bearer $FIA_API_KEY" \
-H "Idempotency-Key: accept-proof-0193f2d0"On the pay page, the client side works in two steps: the upload route returns a signed upload URL for the file, then the proof route creates the proof with claimed_amount_minor, claimed_paid_on, note and the uploaded attachment_id, all optional. Proofs are not on the MCP tool list; your assistant can still record the payment itself with record_payment after you have checked your account.
Your systems can react to new proofs with the payment_proof.submitted webhook event, and to the accepted payment with payment.recorded.
What the client sees
- An I have paid button under the payment details on the pay page.
- A short form for amount, date, note and file.
- The invoice stays unpaid on the pay page until you accept the proof or record the payment. Once you do, the pay page shows the new balance.
Rules and limits
| Rule | Value |
|---|---|
| File types | PDF, PNG, JPEG |
| Maximum file size | 10 MB (proposed) |
| Submissions | 5 per hour per pay link (proposed) |
| File handling | Images are re-encoded and PDFs checked by their content; files are private and never public URLs |
- Paid state. A proof changes nothing about paid state until a person accepts it. Accepting is the audited human confirmation that the paid rule requires.
- Reminders stop. From January 2027, a reminder sequence stops when the client reports payment with a proof, so you do not chase a client who says they paid. If you reject the proof, follow up yourself or send a reminder.
- Stripe payments do not need proofs. Card payments are confirmed by Stripe directly.
- Voided invoices cannot receive new proofs: the pay link is cancelled when you void.
Permissions
| Key | Needed for | Default roles |
|---|---|---|
payments.view | Seeing proofs | Owner, Admin, Editor, Viewer, Accountant |
payments.record | Accepting or rejecting proofs | Owner, Admin, Editor |
Errors
| Code | When |
|---|---|
permission_denied | Your role lacks payments.record |
conflict | The proof was already accepted or rejected |
rate_limited | Too many proofs submitted on one pay link |
token_revoked / token_expired | The pay link is no longer valid |
validation_failed | The file type or size is not allowed |