Quotes
A quote is a priced proposal you send a customer to sign. When they sign it, Kontier puts what was agreed live: the subscription the offer holds is published at exactly the phases, lines and prices on the offer.
That last part is the whole point. Without it, somebody reads a signed PDF and retypes it into the billing system, and the bill quietly stops matching the contract. A quote is the contract and the instruction.
How a quote is built
A quote has two parts, and they are written through different routes:
- The offer itself: who it is for, its title, currency, language, clauses,
contract terms, expiry, signature mode and what the buyer must answer before
signing. This is the quote:
POST /v1/quotesandPATCH /v1/quotes/{id}. - The deal: what the offer sells. A quote carries no plan, lines or term of
its own. It holds one draft revision per subscription it acts on, added
with
POST /v1/quotes/{id}/revisions, and each of those drafts is authored on the subscription's own revision routes, the same ones you use to edit any subscription. Phases, lines, agreed prices, trials, commitments and notice periods all live there.
There is one authoring model for a deal, whether it reaches the customer through an offer or is entered directly on a subscription.
Two kinds
kind is required when you create a quote (unless you duplicate one with
from) and cannot change afterwards.
| Kind | Use it for |
|---|---|
NEW_SUBSCRIPTION | A new customer, or a new subscription for an existing one |
SUBSCRIPTION_UPDATE | Changing an existing subscription: more seats, a different plan, a renegotiated price |
What the offer does to each subscription is stated per revision, by the
kind of POST /v1/quotes/{id}/revisions: new (create a subscription) or
renegotiation (cut an existing one's live revision and offer the follow-on).
The lifecycle
Eight statuses. Most quotes touch four of them.
Code
Draft is yours to edit. Submit (POST /v1/quotes/{id}/submit) runs the
approval checkpoint: when your organisation requires internal sign-off the quote
moves to PENDING_APPROVAL and the call answers 202 with the approval request
id; otherwise it is cleared on your own authority and becomes APPROVED. An
approver who sends it back returns it to DRAFT, with their words in
changes_requested. Send delivers it and the quote becomes SENT. Whether
the buyer has opened it is not a status: read viewed, view_count,
first_viewed_at and last_viewed_at.
SIGNED is the terminal happy state, and the one that puts the deal live.
DECLINED and EXPIRED are not dead ends: revise
(POST /v1/quotes/{id}/revise) reopens the quote as a DRAFT, which is how a
renegotiation works without losing the trail. VOIDED is terminal.
Approval decisions are made in the dashboard; there is no API for them. You can
read the request with GET /v1/approvals/{id}, and the
quote.send checkpoint is configured with the approval.quote.send.* settings
(see Approvals). An API-key caller on a workspace whose send
checkpoint is enabled is refused with 409 APPROVAL_REQUIRED_HUMAN rather than
parked.
actions on a single-quote read says what may be done with the quote right now
(submit, send, remind, reissue, withdraw, record_paper_signature,
revise, void, and what an edit does), by the same rules every write
enforces.
Create one with the API
The walk-through below offers a new customer Premium Support Seat: a 14-day free trial, then an open-ended paid phase at an agreed rate of CHF 150 a seat.
-
Create the quote
The quote is the offer's identity and the people who sign it. It holds no lines yet.
CodeThe response is the quote in
DRAFT.starts_atis optional: omit it and the offer begins on signature. -
Put a subscription on the offer
CodeResponse 201kind: "new"mints a subscription inDRAFTfor the quote's customer, holding an empty draft revision 1.namedefaults to the quote's title.To renegotiate an existing subscription instead, send
{"kind": "renegotiation", "subscription_id": "…", "cut_at": "…"}: its live revision is cut atcut_at(omit it to cut now) and the draft that follows the cut is what the offer holds.adopt_draft: truebinds a draft that is already open on the subscription, as it stands, instead of cutting a new one; withkind: "new"it adopts a subscription that was authored but never activated.An offer may hold several subscriptions;
positionis the order the offer presents them in and the order the signature publishes them in.DELETE /v1/quotes/{id}/revisions/{subscription_id}takes one off again. -
Author the deal on the subscription's draft
Use the
subscription_idfrom the previous step with the subscription's revision routes. For a new subscription, write revision 1 whole:CodePUTreplaces the draft, so sending the same body twice lands the same draft; it takes no Idempotency-Key. For a renegotiation, write the draft the cut opened the same way: send every active phase to the samePUT, with the elapsed part kept as it is (then: "next") and the new phases after it.POST /v1/subscriptions/{id}/revisions/draft/previewtakes the same body and prices it without saving. See Editing a draft.The signature publishes these drafts, not you. While an open quote holds a draft, publishing, activating or discarding it on the subscription is refused with 409
SUBSCRIPTION_DRAFT_ON_OFFER. Editing it is allowed while the quote is not out with the customer: an edit to the draft of a cleared quote sends the quote back toDRAFT, and once it isSENTan edit is refused until you withdraw the signature request. The phase, line and value model is described in full on Subscriptions.GET /v1/quotes/{id}/revisionsreads every subscription on the offer back, each with its draft's phases and every value resolved, andGET /v1/quotes/{id}/effectslists what signing would do to other subscriptions whose exit rules point at a phase this offer moves. -
Send it
CodeThe body is optional. Without it the offer goes to the customer's Quotes & contracts contacts, on the offer's own expiry, with no reminders. Named
recipientsreplace that list for this send only: the first signs, the others are copied, at most three.expires_atcan only narrow the deadline.reminder_every_daysandreminder_maxset automatic nudges.countersignsays what your side does after the buyer signs:NONE,SEAL(applied automatically) orPERSON(wait for thecountersigneryou name).A send answers 200 with the quote in
SENT, or 202 with the approval request id when the send checkpoint parks it inPENDING_APPROVAL. An offer that holds no subscription is refused with 409QUOTE_NO_REVISIONS, and one holding an empty revision cannot be signed. -
Check that it can still be signed
Something the offer depends on can change after it was sent: the renegotiated subscription is cancelled or paused, a followed catalog version moves, a product is archived.
GET /v1/quotes/{id}/signabilityrehearses the buyer's signature (rolled back) and answerssignable, and when it isfalsearefusalwith itscode,messageand thesubscription_id,phaseandproduct_idit is about. A refusal is also recorded on the quote's timeline, andsignability_lost_atis set on the quote. Any other quote (a draft, or one already signed, declined, expired or voided) answerssignable: true. -
Signature
The buyer signs through the link in the mail (see below). Two other routes complete a signature:
- Countersign. When the send named a
PERSONto countersign, that person signs for your organisation after the buyer withPOST /v1/quotes/{id}/signature/countersignand{"consent": true}. It is refused with 409SIGNING_COUNTERSIGN_NOT_READYbefore every party has signed, and with 403SIGNING_NOT_COUNTERSIGNERwhen the request names somebody else. - Mark signed. For a wet-ink or externally signed copy,
POST /v1/quotes/{id}/mark-signedrecords the signature on anAPPROVEDorSENTquote. Upload the signed copy first withPOST /v1/files(owner_kind=quote,category=uploaded_signed_copy) and confirm it withPOST /v1/files/{id}/confirm, then sendsigner_nameand theexecuted_file_id. Any live signature request is withdrawn first, so the buyer cannot also accept in the portal. A quote whosesignature_modeisEXTERNALis never sent; it is recorded this way.
- Countersign. When the send named a
What signing does
The signature flips every draft revision the offer holds to live, in the same
transaction as the quote becoming SIGNED: nothing is copied, the draft rows
become the live ones, all or none. Subscriptions the offer minted (kind: "new")
become ACTIVE beside them; a renegotiated subscription takes the follow-on
revision from its cut. There is no state in which a quote is SIGNED and its
subscriptions are not live.
The quote.signed webhook event is emitted with the signature.
If the quote carries a coupon_code, it is redeemed at signing against the first
subscription the offer creates.
Agreed prices, trials, commitments, notice periods and early-termination fees
are part of the deal, so they are stated on the phases: an agreed rate is a
price value of kind agreed, a trial is a phase at a free price, and a
commitment is the phase's exit (not_before, notice_duration, gate,
fee). A rate that steps up each year is a sequence of phases, each stating its
own agreed price.
Editing after it was sent
PATCH /v1/quotes/{id} edits the offer's content (terms, clauses, intake
demands, layout, language, start date, coupon) freely on a DRAFT. On a
PENDING_APPROVAL or APPROVED quote the edit lands and the quote goes back to
DRAFT. On a SENT quote it amends the offer: the quote stays SENT, the live
signature request is superseded by one over a freshly rendered document, and the
same recipients get the new link. Once the buyer has signed it is refused.
expires_at moves on any open quote.
Adding or removing a subscription is allowed while the deals may still change
(actions.edit.deals): on a DRAFT, and on a PENDING_APPROVAL or APPROVED
quote, which goes back to DRAFT. Otherwise it is refused with 409
QUOTE_REVISIONS_LOCKED.
The buyer's side
A sent quote gets a signing link: the customer opens it, reads the terms, and signs, without an account and without logging in.
- Reissue the link with
POST /v1/quotes/{id}/rotate-tokenif it leaks. The old link stops working immediately and the recipient gets a new one. - Remind with
POST /v1/quotes/{id}/resend. - Withdraw with
POST /v1/quotes/{id}/signature/withdraw: the signing links die and the quote returns toAPPROVED(orDRAFTif it was amended since), ready to be sent again. GET /v1/quotes/{id}/snapshotis the offer exactly as it was sent;GET /v1/quotes/{id}/signingis the signature request in full, andGET /v1/quotes/{id}/signature/documentdownloads the signed record.
Contract text
clauses snapshots library clauses onto the quote at creation. Snapshot is
the operative word: editing the clause library afterwards does not alter a quote
already sent, because what the customer signed must stay what the customer
signed. excluded_clause_ids leaves auto-attached clauses off.
contract_terms carries free text for anything not in the library.
note_for_customer is shown to the buyer. None of that is the commercial deal:
what the customer is charged is decided by the phases on the subscription.
Create one in the dashboard
Over the API, this is POST /v1/quotes; see
Create one with the API.
-
Open the Quotes page
In the sidebar, under Sales, click Quotes. The command palette gets you there too: press ⌘K and start typing
quotes. -
Start the quote
Click Create Quote. The wizard runs in four stages: Customer & basics, Configuration, Document & signing and Review.
-
Write the deal
Configuration is where the products, quantities and agreed rates are written, and where later steps of the deal are added. What the wizard writes is the subscription's draft revision on the offer, the same one the API steps above author.
-
Review it, then create it
Review restates the offer before anything is written. Click Create quote.
Dashboard and API names
| In the dashboard | In the API |
|---|---|
| Submit for approval | POST /quotes/{id}/submit |
| Send | POST /quotes/{id}/send |
| Mark signed | POST /quotes/{id}/mark-signed |
| Revise | POST /quotes/{id}/revise |
| Void | POST /quotes/{id}/void |
| the subscriptions on the offer | GET /quotes/{id}/revisions |
| the buyer's link | signing_link, returned once on a send or reissue only when no email rail is bound |
| Clauses | clauses[], snapshotted at creation |
Where quotes go next
- A signed quote puts its subscriptions live, which then bill normally.
GET /v1/quotes/{id}/eventsis the audit trail: sent, viewed, signed, with timestamps.GET /v1/quotes/{id}/fileslists the documents on the quote, andGET /v1/quotes/{id}/pdfdownloads the proposal PDF.- Quote webhook events include
quote.created,quote.sent,quote.viewed,quote.signed,quote.declinedandquote.expired; see Webhook events.
Reference
| Topic | When you need it |
|---|---|
| Subscriptions | Phases, lines and values: how the deal on an offer is written |
| Prices | Where the catalog numbers on a quote come from |
| Quotes API | Every endpoint, including PDF, attachments and events |