APIv3
Exit Documentation

Estimates

An estimate describes proposed products or services, taxes, pricing, and an expiry date for a customer. API v3 can create, update, convert, and delete eligible open estimates and retrieve existing active estimates.


The estimate object

FieldTypeDescription
idstringUnique estimate UUID.
objectstringAlways estimate.
estimate_numberintegerAccount-assigned estimate number.
custom_estimate_numberstring or nullOptional custom estimate number.
namestring or nullEstimate name.
customer_idstringCustomer UUID.
customer_namestringCustomer display name stored with the estimate.
salesperson_idstringAssigned SalesBinder user UUID.
status_idintegerCurrent estimate status identifier.
statusstring or nullCurrent estimate status name.
issue_datestring or nullEstimate issue date in YYYY-MM-DD format.
expiry_datestring or nullEstimate expiry date in YYYY-MM-DD format.
date_sentstring or nullDate sent in YYYY-MM-DD format.
purchase_order_numberstringCustomer purchase-order reference.
attentionstring or nullAttention line.
shipping_addressstring or nullShipping-address text stored on the estimate.
public_notestring or nullCustomer-facing estimate note.
payment_termsstring or nullPayment terms stored on the estimate.
subtotalstringSubtotal before shipping and taxes, as a four-decimal string.
shippingstringShipping charge as a four-decimal string.
taxstringPrimary tax amount as a four-decimal string.
tax_2stringSecondary tax amount as a four-decimal string.
totalstringEstimate total including shipping and taxes, as a four-decimal string.
created_atstring or nullISO 8601 creation timestamp.
updated_atstring or nullISO 8601 modification timestamp.
linesarrayCurrent estimate line objects. Present only when retrieving one estimate.

Monetary values use the SalesBinder account's base currency. Cost and margin values are not included in estimate API responses.


The estimate line object

FieldTypeDescription
idstringUnique estimate-line UUID.
objectstringAlways estimate_line.
item_idstring or nullRelated inventory item UUID, when present.
namestring or nullLine-item name.
descriptionstring or nullLine-item description.
quantitynumberProposed quantity.
unit_idinteger or nullRelated unit identifier.
unit_pricestringOriginal unit price as a four-decimal string.
discount_percentstringDiscount percentage as a three-decimal string.
discounted_unit_pricestring or nullDiscounted unit price, or null when no discounted price is stored.
tax_ratestringPrimary tax percentage as a three-decimal string.
tax_2_ratestringSecondary tax percentage as a three-decimal string.
subtotalstringQuantity multiplied by the effective unit price, before tax, as a four-decimal string.

Line-item unit costs are intentionally omitted.


Create an estimate

POST/api/v3/estimates

Required scope: estimates:write

Creates an open estimate assigned to the API key's current user. The response is the new estimate object with its calculated line items. Creating an estimate does not send it to the customer, reserve or deduct inventory, or convert it into an invoice or sales order.

Request fields

FieldTypeRequiredDescription
customer_idstringYesActive customer UUID in the current SalesBinder account.
linesarrayYesOne to 100 inventory or service line objects.
namestringNoOptional name for your own reference.
issue_datestringNoIssue date in YYYY-MM-DD format. Defaults using the account and user timezone.
expiry_datestringNoExpiry date in YYYY-MM-DD format. Defaults from the issue date using the account's estimate-expiry setting.
custom_estimate_numberstringNoOptional custom reference, up to 24 characters.
purchase_order_numberstringNoCustomer purchase-order reference.
attentionstringNoAttention line.
shipping_addressstringNoShipping-address text.
public_notestringNoCustomer-facing note.
payment_termsstringNoPayment terms. Account defaults apply when omitted.
shippingnumberNoShipping charge. Defaults to 0.
discount_percentnumberNoEstimate-wide discount from 0 to 100.

An explicitly supplied expiry_date cannot be before issue_date.

Line fields

FieldTypeRequiredDescription
item_idstringInventory linesActive inventory item UUID. The API copies its name, description, cost, and permitted selling price.
item_variation_location_idintegerVariation itemsVariation-location identifier belonging to the selected item and account.
namestringService linesService line name. Ignored for inventory lines.
descriptionstringNoService line description. Inventory descriptions come from the item.
quantitynumberNoPositive quantity. Defaults to 1; unique items are always 1.
unit_pricenumberService linesRequired for service lines. Optional for inventory lines only when the current user may modify selling prices.
tax_ratenumberNoPrimary tax percentage from 0 to 100; defaults to the customer's rate.
tax_2_ratenumberNoSecondary tax percentage from 0 to 100; defaults to the customer's rate.

Estimate number, status, salesperson, account, source, totals, costs, conversion state, and timestamps are controlled by SalesBinder. Supplying unsupported or protected fields returns 422 unsupported_estimate_field rather than silently accepting them.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: warehouse-estimate-2042" \
  --data '{
    "customer_id": "709d2a43-12a9-4d85-a9d9-cb16e66cef53",
    "issue_date": "2026-07-19",
    "shipping": 10,
    "discount_percent": 5,
    "lines": [
      {
        "item_id": "c420fb4b-e98e-4ed4-b2e9-7ad8cc970966",
        "quantity": 2
      },
      {
        "name": "Installation",
        "quantity": 1,
        "unit_price": 75,
        "tax_rate": 5
      }
    ]
  }'

The estimate and its number are saved together. A failed request does not consume an estimate number. Creating an estimate does not change on-hand quantities.


Update an estimate

PATCH/api/v3/estimates/{estimate_id}

Required scope: estimates:write

Updates supported fields on an existing open estimate. Detail fields are partial: fields omitted from the request keep their existing values. SalesBinder recalculates protected totals and estimate quantities automatically. Updating an estimate does not change on-hand inventory.

Only estimates with the Open status can be updated. Declined, expired, closed, and converted estimates are protected; use the separate conversion endpoints documented below.

Updatable fields

FieldTypeDescription
customer_idstringActive customer UUID in the current account. Changing the customer requires a complete lines replacement.
namestringOptional name for your own reference.
issue_datestringIssue date in YYYY-MM-DD format.
expiry_datestringFuture expiry date in YYYY-MM-DD format; cannot be before issue_date.
custom_estimate_numberstringOptional custom reference, up to 24 characters.
purchase_order_numberstringCustomer purchase-order reference.
attentionstringAttention line.
shipping_addressstringShipping-address text.
public_notestringCustomer-facing note.
payment_termsstringPayment terms.
shippingnumberNon-negative shipping charge.
discount_percentnumberEstimate-wide discount from 0 to 100.
linesarrayComplete replacement for the estimate's active non-discount lines.

Estimate number, status, salesperson, account, source, totals, costs, conversion state, and timestamps cannot be changed with this endpoint.

Replacing lines

When lines is omitted, current lines remain unchanged. When lines is included, it is the complete desired set of active non-discount lines:

  • Include an existing line's id to update that line.
  • Omit id to add a new line.
  • Existing lines omitted from the array are removed from the active estimate.
  • A line ID must belong to the same active estimate and can appear only once.
  • Set the estimate-wide discount with discount_percent; do not include the generated discount line in lines.

Each replacement line accepts the same inventory and service fields described under Line fields. At least one line is required when replacing lines.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --request PATCH \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: revise-estimate-2042" \
  --data '{
    "expiry_date": "2026-09-15",
    "shipping": 10,
    "discount_percent": 5,
    "lines": [
      {
        "id": "d96bd8aa-3131-45a8-a6c2-7ab74b79b93a",
        "name": "Installation",
        "quantity": 2,
        "unit_price": 75,
        "tax_rate": 5
      },
      {
        "item_id": "c420fb4b-e98e-4ed4-b2e9-7ad8cc970966",
        "quantity": 1
      }
    ]
  }'

List estimates

GET/api/v3/estimates

Required scope: estimates:read

Returns visible active estimates ordered by estimate number, newest first. Line items are omitted from list responses.

Query parameters

ParameterTypeRequiredDescription
pageintegerNoPage number. Defaults to 1.
limitintegerNoRecords per page. Defaults to 20; maximum 100.
qstringNoSearches customer name, custom estimate number, and estimate name. A numeric value also matches an exact estimate number.
customer_idstringNoReturns estimates for the customer UUID.
status_idintegerNoReturns estimates with the status identifier.
issue_date_fromstringNoIncludes estimates issued on or after this YYYY-MM-DD date.
issue_date_tostringNoIncludes estimates issued on or before this YYYY-MM-DD date.
expiry_date_fromstringNoIncludes estimates expiring on or after this YYYY-MM-DD date.
expiry_date_tostringNoIncludes estimates expiring on or before this YYYY-MM-DD date.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates?customer_id=709d2a43-12a9-4d85-a9d9-cb16e66cef53&limit=20" \
  --header "Authorization: Bearer YOUR_API_KEY"

Example response

json
{
  "object": "list",
  "url": "/api/v3/estimates",
  "has_more": false,
  "data": [
    {
      "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
      "object": "estimate",
      "estimate_number": 2042,
      "customer_id": "709d2a43-12a9-4d85-a9d9-cb16e66cef53",
      "customer_name": "Example Customer",
      "status_id": 5,
      "status": "Open",
      "issue_date": "2026-07-18",
      "expiry_date": "2026-08-17",
      "subtotal": "100.0000",
      "shipping": "10.0000",
      "tax": "5.5000",
      "tax_2": "2.2000",
      "total": "117.7000"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 1,
    "total_records": 1
  }
}

Examples may omit unchanged fields for readability.


Retrieve an estimate

GET/api/v3/estimates/{estimate_id}

Required scope: estimates:read

Returns one visible active estimate. The response includes the lines array, ordered by the estimate's stored line order. Deleted lines are excluded.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --header "Authorization: Bearer YOUR_API_KEY"

If the estimate is outside the current account or assigned-user boundary, is not an estimate, has been archived, or does not exist, the API returns 404 resource_missing.


Convert an estimate to an invoice

POST/api/v3/estimates/{estimate_id}/convert-to-invoice

Required scope: estimates:convert

Converts one visible, open, unconverted estimate into a new unpaid invoice. SalesBinder copies the customer, salesperson, supported details, inventory and service lines, prices, discounts, taxes, shipping, and totals. The estimate is closed and linked to the new invoice, and the invoice is linked back to its source estimate.

The optional request body accepts one field:

FieldTypeRequiredDescription
issue_datestringNoNew invoice issue date in YYYY-MM-DD format. Defaults to the current date in the API user's account timezone.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513/convert-to-invoice" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: convert-estimate-2042" \
  --data '{
    "issue_date": "2026-07-20"
  }'

The response is the complete new invoice object, including its assigned invoice number and lines, with HTTP 201 Created.

The action requires both the user's current estimate-modify and invoice-modify permissions and follows the account's record limit. A prospect associated with the estimate is converted to a customer. Related inventory updates begin only after the conversion succeeds.

An Idempotency-Key is optional but recommended. During the short replay window, retrying the same conversion with the same key and request returns the original 201 response with Idempotent-Replayed: true. Reusing the key with different request data returns a conflict. A later conversion attempt after the estimate has already closed returns 409 estimate_conversion_not_allowed.


Convert an estimate to a sales order

POST/api/v3/estimates/{estimate_id}/convert-to-sales-order

Required scope: estimates:convert_to_sales_order

Converts one visible, open, unconverted estimate into a new open sales order. SalesBinder copies the customer, supported estimate details, inventory and service lines, prices, discounts, taxes, shipping, and totals. The estimate is closed and linked to the new sales order, and the sales order links back to its source estimate.

The request body must be empty. SalesBinder assigns the sales-order number and current issue date.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513/convert-to-sales-order" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: convert-estimate-to-order-2042" \
  --data '{}'

The response is the complete new sales-order object, including its assigned sales-order number and lines, with HTTP 201 Created.

The action requires the user's current estimate-modify, sales-order-list, and sales-order-modify permissions and follows the account's record limit. Related inventory updates begin only after the conversion succeeds.

An Idempotency-Key is optional but recommended. During the short replay window, retrying the same conversion with the same key returns the original 201 response with Idempotent-Replayed: true. A later conversion attempt after the estimate has closed returns 409 estimate_sales_order_conversion_not_allowed.


Decline an estimate

POST/api/v3/estimates/{estimate_id}/decline

Required scope: estimates:decline

Marks one visible, open, unconverted estimate as declined while preserving the estimate and its lines. Declining requires the current user's estimate-list and estimate-modify permissions.

The request body must be an empty JSON object. The general estimate update endpoint cannot set status directly.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513/decline" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: decline-estimate-c40e5d25" \
  --data '{}'

The response is the complete estimate detail object with status 7 (Declined). Repeating the action for an already-declined estimate is safe. An optional Idempotency-Key also replays the original response during the short retry window.

SalesBinder returns 409 estimate_decline_not_allowed for closed, expired, converted, or otherwise ineligible estimates. Declining refreshes estimate availability without changing on-hand inventory.


Delete an estimate

DELETE/api/v3/estimates/{estimate_id}

Required scope: estimates:delete

Permanently deletes an active estimate and its lines when the estimate is still open and has not been converted into an invoice or sales order.

bash
curl "https://yourbusiness.salesbinder.com/api/v3/estimates/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --request DELETE \
  --header "Authorization: Bearer YOUR_API_KEY"
json
{
  "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "object": "estimate",
  "deleted": true
}

The endpoint returns 409 Conflict for closed, declined, expired, converted, or otherwise ineligible estimates. It does not delete an invoice or sales order created from the estimate. Estimate deletion follows the current user's delete permission and assigned-user visibility.

SalesBinder deletes the eligible estimate and its lines together and refreshes related account totals and availability. On-hand inventory quantity is not changed.


Permissions and write behavior

API key scopes can reduce access but cannot exceed the current user's SalesBinder permissions. The user must currently be able to list estimates. Without the current view-all-estimates permission, list and retrieve operations are limited to estimates assigned to that user.

Creating, updating, or declining an estimate also requires the current estimate-modify permission. Invoice conversion requires the current estimate-modify and invoice-modify permissions. Sales-order conversion requires the current estimate-modify, sales-order-list, and sales-order-modify permissions. Both conversions require account record capacity for the new record. Deleting requires the current estimate-delete permission. Inventory selling-price overrides require the current modify-selling-prices permission, and location-limited users can only select inventory in their permitted location.

API v3 does not support sending, reopening, archiving, or restoring estimates. Unsupported fields and actions are rejected.