Invoicing
Estimates
Send a quote before you invoice. Your client accepts it or asks for changes online, and you convert an accepted estimate into an invoice in one step.
An estimate (also called a quote) tells a client what the work will cost before you start. The client opens it online, accepts it or asks for changes, and once it is accepted you turn it into an invoice without typing the lines again. Estimates are on every plan.
How estimates work
An estimate uses exactly the same building blocks as an invoice: the same line items, taxes, discounts, currencies and totals engine. What is different:
- Its own type and sequence. Estimates are numbered separately from invoices, by default
EST-2027-0001,EST-2027-0002and so on. See Document numbering. - No payments. A client does not pay an estimate. Money is collected on the invoice you create from it.
- An estimate page instead of a pay page. The client's link opens
/estimate/[token], where they can Accept or Request changes. - An expiry date. Each business sets how long its estimates stay valid; the starting value is 30 days.
Estimate statuses
| Status | Meaning |
|---|---|
draft | Being prepared. No number yet. |
sent | Numbered and delivered to the client. |
changes_requested | The client asked for changes and left a note. |
accepted | The client accepted it. |
expired | The validity period ran out before it was accepted. |
converted | An invoice was created from it. |
void | Cancelled. It keeps its number. |
The status list is a registry, so the exact names may still change before launch. See Document statuses.
Create and send an estimate in the web app
Start a new estimate
Create a new document and choose the estimate type. Pick the client.
Add lines and terms
Add lines by hand or from your saved items. Write any terms or conditions of the offer in the terms field.
Send it
Click Send. The estimate gets its number, a snapshot is stored, and the client receives an email with a link to the estimate page. You can also copy the link and share it any way you like (Share links).
Wait for the client's answer
When the client clicks Accept, the estimate is marked accepted, an audit entry is written and you are notified. When they click Request changes, their note appears on the estimate so you can revise it.
Convert it to an invoice
Open the accepted estimate and convert it. A new draft invoice is created with the same lines, linked back to the estimate. Review it and send it as usual.
What the client sees
The estimate page is a public page on freeinvoiceautomation.com, themed with your business's logo and colour. It shows the estimate and two choices:
- Accept: records the acceptance, with the time, in the estimate's history.
- Request changes: the client writes a note, which you see on the estimate.
The page has no analytics, no ads and no app chrome. The link is a private token that can be revoked, and it expires. For estimates, the token lifetime follows the estimate validity (30 days to start with).
Through the API and MCP
Create the estimate as a document with "type": "estimate":
curl -X POST "https://api.freeinvoiceautomation.com/v1/documents" \
-H "Authorization: Bearer $FIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9c2e5a10-estimate-redesign" \
-d '{
"type": "estimate",
"client_id": "0193f2a1-0c11-7d2e-9a40-1b2c3d4e5f60",
"currency": "EUR",
"lines": [
{ "description": "Brand redesign, phase 1", "quantity": "1", "unit_price_minor": "250000" }
]
}'Then convert an accepted estimate into an invoice:
curl -X POST "https://api.freeinvoiceautomation.com/v1/documents/0193f2c0-7a1b-7c2d-8e3f-4a5b6c7d8e90/convert" \
-H "Authorization: Bearer $FIA_API_KEY" \
-H "Idempotency-Key: 9c2e5a10-estimate-convert"The response is the new draft invoice. Its links show the estimate it came from.
| Task | Endpoint | MCP tool |
|---|---|---|
| Create a draft estimate | Create an estimate | create_estimate |
| Change it | Update an invoice (same route for every type) | update_invoice |
| Send it | Send a document | send_document |
| Convert to an invoice | Convert an estimate | none |
| What the client calls | Get the estimate page, Accept an estimate, Request changes | none |
Webhooks tell your own systems what happened: estimate.accepted, estimate.changes_requested and estimate.converted.
Deposits and contracts
Two features build on estimates after launch:
- Deposits (week of 25 January 2027): an estimate can carry a deposit, a percentage or a fixed amount due on acceptance or by a date. When the client accepts, the deposit invoice is created automatically. See Deposits and schedules.
- Contracts with e-signature (March 2027): a contract can be attached to an estimate so the client accepts and signs in one step. See Contracts and e-signature.
Rules and edge cases
- Converting copies, it does not move. The estimate stays on record as it was sent; the invoice is a new document with its own invoice number, assigned when you send it.
- Sent estimates change only by revision, just like invoices. If the client requests changes, your edit creates a new revision and the earlier version stays readable.
- Drafts can be deleted, because they have no number. A sent estimate can be voided but never deleted.
- Client acceptance is audited. The acceptance is written to the audit log with the time it happened.
Permissions
| Action | Permission key |
|---|---|
| View estimates | documents.view |
| Create estimates and convert them | documents.create |
| Edit and revise | documents.edit |
| Send and share | documents.send |
| Void | documents.void |
Your client needs no account and no password: the private link is their access.
Errors you may see
| Code | Meaning |
|---|---|
validation_failed | A field is missing or invalid. |
document_not_editable | The estimate was sent; edit it by revision. |
document_voided | The estimate is void. |
token_expired | The client opened an expired estimate link. Share a new link with them. |
token_revoked | The link was revoked. |