SoftSolzSoftSolz
HomeAPI GuideAPI ReferenceWidget Tester

Quotes and Signatures

Create a priced quote, send it for signing, and read what happened to it.

Build a quote from priced lines, then send it. The customer accepts on a public page without logging in, and the acceptance is fingerprinted against the quote as it stood at that moment.

Create a quote

bash
curl -X POST https://app.softsolz.uk/api/v1/services/quotes/quotes \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"title":"Website rebuild","contact_id":"...","lines":[{"description":"Design","quantity":1,"unit_price_cents":150000}]}'

Send it

bash
curl -X POST https://app.softsolz.uk/api/v1/services/quotes/quotes/{quote_id}/send \
-H "Authorization: Bearer sk_live_your_key"

Money is always in minor units (pence or cents), so 50000 is 500.00. Totals are worked out for you: the discount comes off the subtotal first, then each line's tax is charged on what is left.

What the send reply tells you

The reply holds the quote plus links (one private signing URL per person who still has to sign), delivery (whether each email went out and, if not, why) and email_warning, which is null when every email was sent. When it is set, give the link to the customer yourself. Sending again returns the same links.

Mistakes are refused, never fixed quietly

A value that is not valid answers 400 with a stable code and the field in details.field. Nothing is rounded, clamped or cut off.

  • invalid_unit_price: a price that is negative or not a whole number of minor units.
  • invalid_tax_rate: a tax rate below 0 or above 100.
  • invalid_discount and discount_too_large: a negative discount, or one above the subtotal.
  • title_too_long and line_description_too_long: over 200 and 500 characters.
  • quote_number_taken (409): your own quote_number is already used.
  • quote_expired (409): the draft's valid_until is in the past, so it cannot be sent.

Following what happens

Register a webhook for quotes.sent, quotes.viewed, quotes.signer_signed, quotes.countersigned, quotes.accepted, quotes.declined, quotes.expired and quotes.converted. If a signer from your business is on the quote, it is only accepted once that person has signed as well. Turning an accepted quote into an invoice is done in the dashboard.

A sent quote is locked

Once sent, a quote cannot be edited - send a replacement instead. That is what keeps the acceptance record meaningful, so do not build a flow that expects to patch a quote after sending. The public API creates, reads and sends quotes; adding signers, chasing, declining and converting are done in the dashboard.

Next

See every field in the API Reference, or the walkthrough on docs.softsolz.uk.