Estimates
An estimate is a quote you send before the work. Your customer opens a hosted page, reads the full breakdown, and accepts or declines it there. An accepted estimate becomes a draft invoice, so you never retype the lines.
Estimates are included on every plan. They live on their own page in the dashboard (Estimates, under Invoices) and never appear in your invoice list, ageing report, revenue, VAT report or dashboard totals. An estimate is a promise to bill, not a bill.
How an estimate moves
Section titled “How an estimate moves”draft → sent → accepted → converted (a draft invoice now exists) → declined → expireddraft, sent, declined or expired → voidaccepted is momentary: accepting an estimate and creating its invoice happen in one step, so you will see converted on the estimate, and the estimate.accepted webhook still fires first.
| Status | Meaning |
|---|---|
| Draft | Saved, not sent. Fully editable, has no number yet. |
| Sent | Emailed to the customer and waiting for a decision. |
| Accepted | The customer accepted. Converts to an invoice straight away. |
| Converted | A draft invoice was created from it. Terminal. |
| Declined | The customer declined, with an optional reason. You can revise and resend it. |
| Expired | The expiry date passed without a decision. You can revise and resend it. |
| Void | You cancelled it. Terminal. Not possible once converted. |
Creating and sending
Section titled “Creating and sending”- Go to Estimates and click New estimate.
- Pick or add a customer. A customer no longer needs a wallet, an email is enough. See Customers.
- Add line items, exactly as on an invoice, including discounts and per-line tax if you use itemized tax.
- Set an expiry date if the price is only good for a while. New estimates default to 30 days. The default is not currently configurable.
- Add terms, a memo or a footer, then Send.
Sending assigns the number (EST-0001, or TEST-EST-0001 in test mode), records the tax labels as they stand today, and emails the customer a link to the hosted page. If you have late fees switched on, the estimate also states the late-fee terms, so the customer sees them before they accept.
Working from the list
Section titled “Working from the list”The list shows 10 estimates at a time, or 20 if you choose that in the pager (“Page X of Y” with First, Previous, Next and Last), with the total number of estimates shown below the list. Filtering by status or searching takes you back to the first page, and the total follows the filter and search you have set. If Plirin cannot count the estimates, the list still loads and a notice with a Retry button takes the place of the total.
Click a row to open the estimate. The ⋮ menu at the end of each row offers the same actions as the estimate itself, limited to what its status allows: Send for a draft, Convert now for a sent estimate, Edit, Duplicate, Void, and links to the customer page and the PDF once it has been sent. Convert now and Void ask you to confirm first.
To act on several at once, tick them in the list, or tick the box in the header to select the whole page, and choose Send or Void from the bar at the bottom of the screen. Each button counts only the selected estimates it applies to: Send takes the drafts and Void takes those not yet converted or void. Anything else in your selection is skipped, and the confirmation says how many. Each estimate is sent or voided on its own, so one that can’t be, such as a draft with no customer email, is reported by name and the rest still go through. Changing the filter, the search or the page clears the selection.
What the customer sees
Section titled “What the customer sees”The hosted page (/e/<slug>) shows your business, the estimate number and revision, the full money breakdown, the expiry date and any late-fee terms. To accept, the customer types their full name and ticks a box that reads “I accept estimate EST-0042 rev 2 on behalf of” their company or name, as they were when you sent that revision. Editing the customer’s company later does not change it. Declining takes an optional reason.
The page follows the same rules as the hosted invoice page: an unknown, draft or void link shows the same not-found page, and once the customer has decided, the page shows the outcome instead of the buttons.
Evidence of acceptance
Section titled “Evidence of acceptance”Each acceptance stores a permanent record:
- the typed name and the email address the estimate was sent to
- the exact consent sentence the customer agreed to
- a fingerprint (SHA-256) of the revision they saw, so the terms cannot be changed after the fact without it showing
- the IP address, browser and time (UTC)
This is a simple electronic signature, which is enough for most quotes under eIDAS, the US ESIGN Act and the UK Electronic Communications Act. It is not an advanced or qualified signature. If a contract needs one, use a signature service for the contract itself.
On the estimate you will see a line such as “Accepted by J. Smith, 28 Sep 2026 14:03 UTC”. Decisions are never edited or deleted.
Editing a sent estimate
Section titled “Editing a sent estimate”Editing an estimate that is sent, declined or expired creates a new revision and sends it again. The customer can no longer act on the old one: accepting revision 1 after you sent revision 2 fails with a message asking them to review the new version. A declined revision stays on record, and the new revision can be decided fresh. The customer is the one thing a revision cannot change: to quote someone else, void the estimate and create a new one (the API returns 409 with code estimate_customer_locked). While an estimate is a draft, picking a different customer also replaces the name and email on it.
Expiry
Section titled “Expiry”Expiry is counted on your calendar, using the timezone in your profile. An estimate that expires on 15 November can still be accepted at 23:59 on the 15th and not at 00:00 on the 16th. Three days before expiry the customer gets one reminder email, when an expiry is set. When the date passes, the estimate moves to expired and you are emailed. An expiry date before today is refused when you create, edit or send an estimate, so a draft left unsent past its expiry needs a new date before it can go out. The API returns 400 with code estimate_expiry_in_past.
Converting to an invoice
Section titled “Converting to an invoice”Accepting creates a draft invoice. It copies the lines, tax treatment, discount, currency, customer, memo and footer from the revision the customer accepted, and its total equals the estimate’s to the smallest currency unit. It is priced from what the customer signed, never re-priced from your catalog. You review the draft and send it like any invoice, and its drawer shows “From estimate EST-0042 rev 2”. When you send it, it carries the late-fee terms shown on the estimate the customer accepted, even if you have changed your late-fee settings since.
The invoice is created in the same environment as the estimate. An estimate made in test mode produces a test invoice even if you have gone live since.
Estimate files never appear on your customer’s estimate page, but they are copied onto the draft invoice with the same Visible to customer setting, which starts off, so a file stays internal unless you switch it on. Switch on the ones your customer should see on the invoice. If your plan’s file storage cannot hold all of them, the conversion still goes ahead and the files that did not fit stay on the estimate; the audit entry records how many were copied and how many were not. See Attachments.
If the customer agreed by phone, use Convert now, which works on a sent estimate. It records the estimate as accepted by you, with no signature, and creates the draft invoice.
Permissions
Section titled “Permissions”Every estimate action needs the invoice.manage permission.
API and webhooks
Section titled “API and webhooks”Estimates have a REST API (/api/v1/estimates) and SDK methods estimates.create, list, retrieve, update, send, void, convert and pdf. See the TypeScript and Python SDK pages. Without a plan that includes estimates, calls return 403 plan_limit_exceeded, and a test key only sees test estimates.
The GraphQL estimate operations serve the dashboard and are denied to API keys, so integrations use REST.
Events: estimate.sent, estimate.accepted, estimate.declined, estimate.expired, estimate.converted and estimate.voided. See Webhook events and the payload reference.