Estimates
Quotes/estimates with line items, totals, and a send + convert flow.
/estimatesList estimates
Returns a cursor-paginated list of estimates for the authenticated organization, ordered by document id. Soft-deleted estimates are excluded. Requires scope: estimates:read.
Response 200
Errors
/estimatesCreate an estimate
Creates a new estimate. The organization and the actor (CreatedBy) are always taken from the API key context, never the request body. Per-line amounts and the subtotal/taxTotal/total are computed server-side from the supplied line items and are not trusted from the body. Requires scope: estimates:write.
Request body
Response 201
idrequiredobjectrequirednumberuuidestimateNamesubjectclientIdclientNameclientstatusrequiredsentlineItemsrequiredentryIditemIdnamerequireddescriptionquantityrequiredunitPricerequiredunitCosttaxabletaxRateamountrequiredtypesignaturesidsignerTypesignerNamesignerEmailsignatureTitlesignatureDatasignedByUserIdsignedAtsubtotalrequiredsubTotaltaxTotalrequiredtotalrequiredtotalAmountdiscountTotaltipTotaltaxableTotaltaxRateitemCostTotallaborCostTotaltotalsSnapshotcurrencyrequiredtermsnotesdiscountNameorganizationCompanyIdbilledFromappointmentIdappointmentUUIDappointmentDocIdcustomFieldsconvertedToInvoiceIdconvertedToInvoiceUuidconvertedAtissueDateexpiryDateexpiresAtreminderSentAtcreatedAtupdatedAtErrors
/estimates/{id}Retrieve an estimate
Returns a single estimate by id. A record belonging to another organization returns 404 rather than 403, so this can never confirm cross-tenant existence. Requires scope: estimates:read.
Parameters
Path
idrequiredResponse 200
idrequiredobjectrequirednumberuuidestimateNamesubjectclientIdclientNameclientstatusrequiredsentlineItemsrequiredentryIditemIdnamerequireddescriptionquantityrequiredunitPricerequiredunitCosttaxabletaxRateamountrequiredtypesignaturesidsignerTypesignerNamesignerEmailsignatureTitlesignatureDatasignedByUserIdsignedAtsubtotalrequiredsubTotaltaxTotalrequiredtotalrequiredtotalAmountdiscountTotaltipTotaltaxableTotaltaxRateitemCostTotallaborCostTotaltotalsSnapshotcurrencyrequiredtermsnotesdiscountNameorganizationCompanyIdbilledFromappointmentIdappointmentUUIDappointmentDocIdcustomFieldsconvertedToInvoiceIdconvertedToInvoiceUuidconvertedAtissueDateexpiryDateexpiresAtreminderSentAtcreatedAtupdatedAtErrors
/estimates/{id}Update an estimate
Updates an existing estimate. Only the supplied fields are changed. When lineItems are supplied, the subtotal/taxTotal/total are recomputed server-side and never trusted from the body. Setting status to "sent" stamps sentAt; setting it to "draft" clears the sent flag. Requires scope: estimates:write.
Parameters
Path
idrequiredRequest body
Response 200
idrequiredobjectrequirednumberuuidestimateNamesubjectclientIdclientNameclientstatusrequiredsentlineItemsrequiredentryIditemIdnamerequireddescriptionquantityrequiredunitPricerequiredunitCosttaxabletaxRateamountrequiredtypesignaturesidsignerTypesignerNamesignerEmailsignatureTitlesignatureDatasignedByUserIdsignedAtsubtotalrequiredsubTotaltaxTotalrequiredtotalrequiredtotalAmountdiscountTotaltipTotaltaxableTotaltaxRateitemCostTotallaborCostTotaltotalsSnapshotcurrencyrequiredtermsnotesdiscountNameorganizationCompanyIdbilledFromappointmentIdappointmentUUIDappointmentDocIdcustomFieldsconvertedToInvoiceIdconvertedToInvoiceUuidconvertedAtissueDateexpiryDateexpiresAtreminderSentAtcreatedAtupdatedAtErrors
/estimates/{id}Delete an estimate
Soft-deletes an estimate (sets softDeleted, deletedAt). There is no hard delete for estimates. Returns a deletion confirmation object. Requires scope: estimates:write.
Parameters
Path
idrequiredResponse 200
idrequiredobjectrequireddeletedrequiredErrors
/estimates/{id}/sendMark an estimate as sent
Records the estimate as sent (sets sent, stamps sentAt; transitions a draft to "sent"). Already-resolved statuses (accepted, declined, expired, void) keep their status. This does NOT email the estimate - the caller drives their own delivery. Requires scope: estimates:write.
Parameters
Path
idrequiredResponse 200
idrequiredobjectrequirednumberuuidestimateNamesubjectclientIdclientNameclientstatusrequiredsentlineItemsrequiredentryIditemIdnamerequireddescriptionquantityrequiredunitPricerequiredunitCosttaxabletaxRateamountrequiredtypesignaturesidsignerTypesignerNamesignerEmailsignatureTitlesignatureDatasignedByUserIdsignedAtsubtotalrequiredsubTotaltaxTotalrequiredtotalrequiredtotalAmountdiscountTotaltipTotaltaxableTotaltaxRateitemCostTotallaborCostTotaltotalsSnapshotcurrencyrequiredtermsnotesdiscountNameorganizationCompanyIdbilledFromappointmentIdappointmentUUIDappointmentDocIdcustomFieldsconvertedToInvoiceIdconvertedToInvoiceUuidconvertedAtissueDateexpiryDateexpiresAtreminderSentAtcreatedAtupdatedAtErrors
/estimates/{id}/convert-to-invoiceConvert an estimate to an invoice
Creates a new invoice from the estimate, copying its line items, client fields, and billed-from fields. The new invoice starts as status "draft" with balance equal to its total and amountPaid 0. The estimate is stamped with the resulting invoice id. Guards against double-conversion: if the estimate was already converted, returns 422. Requires both scopes: estimates:write and invoices:write.
Parameters
Path
idrequiredResponse 201
idrequiredobjectrequirednumberclientIdstatusrequiredlineItemsrequiredentryIditemIdnamerequireddescriptionquantityrequiredunitPricerequiredunitCosttaxabletaxRateamountrequiredtypesubtotalrequiredtaxTotalrequiredtotalrequiredbalancerequiredamountPaidrequiredcurrencyrequiredconvertedFromEstimateIdcreatedAtupdatedAt