Quotes are offers a buyer signs. A quote names the subscriptions it acts on (POST /quotes/{id}/revisions): a new DRAFT subscription, or a new revision of an existing one, whose phases and lines are authored with the subscription revision operations. Sending the quote gives the buyer a signing link; signing publishes the bound revisions. Contract clauses and quote presets are managed here too.
List contract clauses
Lists the org's reusable contract clauses, keyset-paginated newest first. Archived clauses are excluded unless include_archived is set: this list is what the quote clause picker reads. Each clause carries its per-locale bodies, the ids of the products, plans and quote presets it is attached to, and a read-only body resolved for the org's default locale.
Required scope: quotes.read (Read quotes).
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
include_archivedInclude archived clauses. Off by default: this list is the quote picker's source.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List contract clauses › Responses
OK
Create a contract clause
Adds a reusable clause to the library. A clause is ONE record with a body per locale, not one record per language: quotes snapshot the body for the org's contract language on insert.
Required scope: quotes.write (Write quotes).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a contract clause › Request Body
Clause text keyed by locale ("en", "de", "fr", "es", "it", "pt", "nl", "ja"). At least one required.
nameClause name.
countryISO 3166-1 alpha-2 country scope; null means global.
Create a contract clause › Responses
Created
Get a contract clause
Returns a single contract clause.
Required scope: quotes.read (Read quotes).
path Parameters
idClause UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a contract clause › Responses
OK
Update a contract clause
Patches a library clause; omitted fields stay untouched, and a present bodies replaces the whole per-locale set. Existing quote snapshots are unaffected — the body a quote froze is the document, and no library edit reaches it.
Required scope: quotes.write (Write quotes).
path Parameters
idClause UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a contract clause › Request Body
Replaces the whole per-locale body set. Omit to leave it untouched.
countrynameUpdate a contract clause › Responses
OK
Archive a contract clause
Retires a library clause: it leaves the picker and stops auto-attaching from any product, plan or preset it hangs off. Reversible via restore. Quote snapshots and their headings are untouched — archiving retires a clause from the catalog, it never rewrites a document that already quoted it.
Required scope: quotes.write (Write quotes).
path Parameters
idClause UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Archive a contract clause › Responses
OK
Restore an archived contract clause
Returns an archived clause to the picker; it resumes auto-attaching wherever it is still attached.
Required scope: quotes.write (Write quotes).
path Parameters
idClause UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Restore an archived contract clause › Responses
OK
Restore an archived contract clause
Deprecated: use POST /clauses/{id}/restore instead. Removed on 2026-11-30.
Returns an archived clause to the picker; it resumes auto-attaching wherever it is still attached.
Required scope: quotes.write (Write quotes).
path Parameters
idClause UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Restore an archived contract clause › Responses
OK
List the contract clauses attached to a plan
Returns the library clauses attached to this plan, which a quote containing it picks up automatically. Archived clauses are included so an attachment to a retired clause stays visible and removable.
Required scope: quotes.read (Read quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the contract clauses attached to a plan › Responses
OK
Attach contract clauses to a plan (additive)
Attaches the given clause IDs without removing existing ones, and returns the resulting set. Idempotent: re-sending an already-attached id is a no-op. Attachment is to the plan ROOT, not to a version — a clause is a policy about the thing you sell, not about a revision of its price, and the freeze that matters happens when a quote snapshots the text.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Attach contract clauses to a plan (additive) › Request Body
clause_idsLibrary clause IDs.
Attach contract clauses to a plan (additive) › Responses
OK
Detach contract clauses from a plan
Removes the clause IDs given in clause_ids from this plan and returns what is left. Already-absent ids are ignored. Quotes already created keep their snapshots.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
query Parameters
clause_idsLibrary clause IDs to detach. Repeatable or comma-separated.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Detach contract clauses from a plan › Responses
OK
List the contract clauses attached to a product
Returns the library clauses attached to this product, which a quote containing it picks up automatically. Archived clauses are included so an attachment to a retired clause stays visible and removable.
Required scope: quotes.read (Read quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the contract clauses attached to a product › Responses
OK
Attach contract clauses to a product (additive)
Attaches the given clause IDs without removing existing ones, and returns the resulting set. Idempotent: re-sending an already-attached id is a no-op. Attachment is to the product ROOT, not to a version — a clause is a policy about the thing you sell, not about a revision of its price, and the freeze that matters happens when a quote snapshots the text.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Attach contract clauses to a product (additive) › Request Body
clause_idsLibrary clause IDs.
Attach contract clauses to a product (additive) › Responses
OK
Detach contract clauses from a product
Removes the clause IDs given in clause_ids from this product and returns what is left. Already-absent ids are ignored. Quotes already created keep their snapshots.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
query Parameters
clause_idsLibrary clause IDs to detach. Repeatable or comma-separated.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Detach contract clauses from a product › Responses
OK
List quote presets
Lists the org's reusable quote presets, keyset-paginated newest first.
Required scope: quotes.read (Read quotes).
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List quote presets › Responses
OK
Create a quote preset
Creates a reusable quote preset (expiry default, intake gates, note/terms, plan pin).
Required scope: quotes.write (Write quotes).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a quote preset › Request Body
namePreset name.
activeDefaults to true when omitted.
contract_termsdefault_expiry_daysPublic-link lifetime in days for quotes created from this preset.
descriptiondocument_template_idDocument template to render quotes from this preset with. Omit to use the organization's quote default.
note_for_customerplan_idplan_versionWhat quotes from this preset demand of the buyer before signing, destinations included.
require_payment_methodrequire_shippingrequire_vat_idCreate a quote preset › Responses
Created
Get a quote preset
Returns a single quote preset.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a quote preset › Responses
OK
Delete a quote preset
Hard-deletes a quote preset. Existing quotes keep their snapshot (their preset_id nulls out).
Required scope: quotes.write (Write quotes).
path Parameters
idQuote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Delete a quote preset › Responses
No Content
Update a quote preset
Patches a quote preset; omitted fields stay untouched.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a quote preset › Request Body
activecontract_termsdefault_expiry_daysdescriptiondocument_template_idPin a document template; null unpins it so quotes fall back to the organization's quote default; omitted leaves the current pin.
namenote_for_customerplan_idplan_versionReplace what quotes from this preset demand of the buyer, destinations included. Send [] to require none.
require_payment_methodrequire_shippingrequire_vat_idUpdate a quote preset › Responses
OK
List the contract clauses attached to a quote preset
Returns the library clauses attached to this quote preset, which a quote containing it picks up automatically. Archived clauses are included so an attachment to a retired clause stays visible and removable.
Required scope: quotes.read (Read quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the contract clauses attached to a quote preset › Responses
OK
Attach contract clauses to a quote preset (additive)
Attaches the given clause IDs without removing existing ones, and returns the resulting set. Idempotent: re-sending an already-attached id is a no-op. Attachment is to the quote preset ROOT, not to a version — a clause is a policy about the thing you sell, not about a revision of its price, and the freeze that matters happens when a quote snapshots the text.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Attach contract clauses to a quote preset (additive) › Request Body
clause_idsLibrary clause IDs.
Attach contract clauses to a quote preset (additive) › Responses
OK
Detach contract clauses from a quote preset
Removes the clause IDs given in clause_ids from this quote preset and returns what is left. Already-absent ids are ignored. Quotes already created keep their snapshots.
Required scope: quotes.write (Write quotes).
path Parameters
idProduct, plan or quote preset UUID
query Parameters
clause_idsLibrary clause IDs to detach. Repeatable or comma-separated.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Detach contract clauses from a quote preset › Responses
OK
List who may sign for your organisation
The active members whose roles grant quotes.sign_for_org, ordered by name: who a send or a reassignment may name to sign an offer for the organisation.
Required scope: quotes.read (Read quotes).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List who may sign for your organisation › Responses
OK
List quotes
Lists quotes with cursor-based pagination, per-status facet counts, a quote_number/title search, and the unified field.op=value filter grammar (customer_id, kind, owner_user_id, status, expires_at, value_amount).
Required scope: quotes.read (Read quotes).
query Parameters
customer_idFilter on customer_id (uuid). Operators: eq — dot grammar, e.g. customer_id.eq=value; a bare customer_id=value means eq.
expires_atFilter on expires_at (date-time). Operators: gte, lte — dot grammar, e.g. expires_at.gte=value; a bare expires_at=value means eq.
idFilter on id (uuid). Operators: eq, in — dot grammar, e.g. id.in=value; a bare id=value means eq. A bare comma-separated value is in-sugar: id=a,b means id.in=a,b.
kindFilter on kind (enum). Operators: eq, in — dot grammar, e.g. kind.in=value; a bare kind=value means eq. A bare comma-separated value is in-sugar: kind=a,b means kind.in=a,b. Legal values: NEW_SUBSCRIPTION, SUBSCRIPTION_UPDATE.
owner_user_idFilter on owner_user_id (uuid). Operators: eq — dot grammar, e.g. owner_user_id.eq=value; a bare owner_user_id=value means eq.
value_amountFilter on value_amount (number). Operators: gte, lte — dot grammar, e.g. value_amount.gte=value; a bare value_amount=value means eq.
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
searchCase-insensitive match over quote_number and title; relevance-ranked (exact > prefix > substring) unless an explicit sort is given
statusFilter by quote status. Filterable fields (customer_id, kind, owner_user_id, status, expires_at, value_amount) accept apifilter operator suffixes in the dot grammar, e.g. status.in=SENT,SIGNED
countersign_dueOnly the offers waiting on a person to sign for your organisation: me = the ones you may sign now, any = all of them (including those named to a colleague or signed at the signing provider).
subscription_idOnly the offers that act on this subscription - the quotes holding a draft revision for it. Resolved through quote_revisions and applied as an id set.
sortOrdering: created_at, quote_number, title, kind, status, value_amount, sent_at or expires_at, each with an optional :asc/:desc suffix (default created_at:desc). value_amount orders by currency first and the amount within it - an amount across currencies is not a comparable quantity. Quotes with no sent_at/expires_at group together at one end. An unknown value is rejected. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page. Sorting suppresses relevance ranking when search is also given.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List quotes › Responses
OK
Create a quote
Creates a DRAFT quote: the identity of an offer and the people who will sign it. A preset prefills unset fields (the operator body wins). It carries no lines — what the offer sells is added afterwards, one draft revision per subscription, through POST /quotes/{id}/revisions.
Required scope: quotes.write (Write quotes).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a quote › Request Body
Library clauses to snapshot onto the quote; body is an optional override of the library text.
contract_termscopy_contact_idsCustomer contacts copied on the signature request, only beside signer_contact_id.
countersignWhat your organisation does once the buyer has signed. none: nothing. seal: the signed copy is sealed in the organisation's name. person: a member signs for the organisation, and the document shows their signature lines. Omit to use the organisation's default (signing.countersign_default).
countersign_orderWhen a person countersignature is made: after_buyer (the buyer signs first) or before_send (your organisation signs first, the buyer receives the offer signed). Omit to use the organisation's default.
countersigner_user_idThe member who signs for your organisation under person; they must hold quotes.sign_for_org. null: anyone who may (the sender is asked). Omit to use the organisation's default signer.
coupon_codecreated_bycurrencycustom_fieldscustomer_idThe buyer. Required unless from is given; a duplicate omitting it is for the source's customer.
document_template_idDocument template this quote renders through. Omit to inherit the preset's pinned layout, then the organization's quote default.
excluded_clause_idsAuto-attached clause ids to leave off this quote. Each id must be one the catalog attaches to this offer, and must not also appear in clauses.
expires_atfromDuplicate this quote: unset fields are taken from it and every subscription it offers is copied onto the new draft.
kindRequired unless from is given. A duplicate keeps the source's kind, because it keeps the source's subscriptions: omit it, or name the source's own (another is refused with QUOTE_KIND_CONTRADICTS_SOURCE).
localeLanguage the offer is for (en, de, fr, es, it, pt, nl, ja). Drives the PDF, the buyer mail and the language a clause body is snapshotted in. Omit to inherit the customer's locale, then the organization default.
note_for_customerowner_user_idpreset_idreminder_every_daysRemind the buyer of an unsigned offer every N days. Omit for no automatic reminders.
reminder_maxAt most this many reminders; needs reminder_every_days. Omit for the provider's own cap.
What the buyer must answer before signing, each entry naming a custom-field key, WHERE the answer goes after signature (target) and what happens when the destination already holds a value (on_conflict). Omit to inherit the preset's list.
require_payment_methodrequire_shippingrequire_signer_roleAsk the signer for their role or title before signing. Omit to inherit the preset's choice (none).
require_vat_idsignature_modeHow the buyer signs: BASIC (typed name, the default) or OTP (typed name and an emailed code; the offer is not sent while this workspace cannot mail the code). EXTERNAL is refused: a paper signature is recorded with mark-signed in any mode.
signer_contact_idThe customer contact who signs. Omit to send to the customer's Quotes & contracts contacts (their primary signs, the others are copied), else the customer's own email.
sourcestarts_atWhen the offer begins. Omit to begin on signature.
titleCreate a quote › Responses
Created
Get a quote
Retrieves a single quote by ID, including its priced lines, the signature summary when one exists, and the portal-relative public link path.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a quote › Responses
OK
Update a quote
Edits the mutable quote fields, judged by what actually changes (the quote's actions.edit). The offer's content — its terms, clauses, intake demands, layout, language, start date, coupon and pinned value — is edited freely on a DRAFT; on a PENDING_APPROVAL or APPROVED quote the edit lands and the quote goes back to DRAFT (its clearance was for other content, and a pending approval is cancelled); on a SENT quote it amends the offer: the quote stays SENT, the live signature request is superseded (CANCELLED, reason SUPERSEDED, the old link dead) by one over a freshly rendered document, and the same recipients are sent the new link — refused with 409 QUOTE_SIGNED_IN_PORTAL once the buyer has signed, and with 409 QUOTE_AMEND_NEEDS_APPROVAL when the quote.send approval checkpoint would require approval for the amended offer (withdraw it and send it for approval again; actions.edit.content_refusal predicts it). expires_at moves on any open quote; on a SENT one the signature request's deadline moves with it, because the two are one deadline — and a deadline moved past the one the signature provider holds re-issues the request over the new deadline, the way an amendment does. The owner and the metadata are not the offer and never change its status. DECLINED and EXPIRED quotes are reopened with Revise before their content or deadline changes, and SIGNED/VOIDED quotes are immutable.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a quote › Request Body
Replace the quote's clause snapshots. Send [] to carry none. Omit to leave them untouched.
contract_termscopy_contact_idsReplace the contacts copied (only beside signer_contact_id). Send [] to copy nobody.
countersignWhat your organisation does once the buyer has signed: none, seal or person. Editable until the quote is sent.
countersign_orderWhen a person countersignature is made: after_buyer or before_send.
countersigner_user_idThe member who signs for your organisation under person (must hold quotes.sign_for_org); null: anyone who may.
coupon_codePromotion coupon the buyer redeems; null removes it.
custom_fieldsdocument_template_idPin the document template this quote renders through; null unpins it so the quote falls back to the organization's quote default; omitted leaves the current pin.
excluded_clause_idsAuto-attached clause ids to leave off this quote. Each id must be one the catalog attaches to this offer, and must not also appear in clauses.
expires_atPublic-link expiry; null removes it.
localeLanguage the offer is for (en, de, fr, es, it, pt, nl, ja); null inherits the customer's locale, then the organization default.
note_for_customerowner_user_idreminder_every_daysRemind the buyer every N days; null: no automatic reminders (clears reminder_max too).
reminder_maxAt most this many reminders; null: the provider's own cap.
Replace what the buyer must answer before signing, destinations included. Send [] to require none.
require_payment_methodrequire_shippingrequire_signer_roleAsk the signer for their role or title before signing.
require_vat_idsignature_modeHow the buyer signs: BASIC or OTP. EXTERNAL is refused. On a sent offer a change replaces the buyer's signing link; a change to OTP is refused (409 QUOTE_OTP_UNDELIVERABLE) while the code cannot be mailed.
signer_contact_idThe customer contact who signs; null goes back to the customer's Quotes & contracts contacts and drops the copies.
starts_atMove the offer's start date; null drops it so the offer begins on signature.
titlevalue_overridePin the quote's headline value to this major-unit decimal; null unpins it so the value tracks the revisions again.
Update a quote › Responses
OK
The buyer page as the buyer sees it
The same payload the buyer's link page gets (PublicQuotePageResponse: the document, the branding, signing_documents), for the quote's Preview tab, with viewer operator. Read-only: no link is used, nothing is recorded, no saved form is read. signing_documents is the frozen request's once the quote was sent, else what a send would freeze from the live field layouts; its bytes are GET /quotes/{id}/buyer-page/signing-document.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
query Parameters
localeThe language to show the page in; omitted, the page's own cascade decides (the offer's language, the customer's, the organization default).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
The buyer page as the buyer sees it › Responses
OK
The PDF the buyer page's documents to sign are in
The PDF GET /quotes/{id}/buyer-page's signing_documents describe, page numbers included: once the quote was sent, the document its signature request froze; before, the offer's document with its laid-out attachments merged behind it, rendered and merged exactly as the send will and stored nowhere. 404 when the quote has no documents to sign. Never cached.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
The PDF the buyer page's documents to sign are in › Responses
The PDF
What this offer does to other subscriptions
Returns the co-termination effects the offer carries AS IT STANDS: one entry per subscription outside the offer whose exit rule points at a phase this offer moves, with what its commitment becomes. Computed from the exit rules on every call — the effect follows the phase, so it moves when the offer moves — and frozen only at send, where /quotes/{id}/snapshot answers with the listing the buyer was actually shown.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
What this offer does to other subscriptions › Responses
OK
List quote tracking events
Returns the quote's append-only tracking timeline (created, submitted, approved, sent, viewed, signed, ...), keyset-paginated newest first.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List quote tracking events › Responses
OK
List the documents on a quote
Returns the quote's documents. Uploads that were never confirmed are not listed; pass status=quarantined to see the uploads that were refused.
Required scope: quotes.read (Read quotes).
path Parameters
idThe owning record's UUID
query Parameters
includeExtra data to add to the response: has_signing_fields, origin. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. has_signing_fields is sent without being asked until 2026-11-30; after that date it is sent only when named here. origin is sent without being asked until 2026-11-30; after that date it is sent only when named here.
statusWhich documents to list. Defaults to the accepted ones; quarantined lists the uploads that were refused.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the documents on a quote › Responses
OK
Record a signature made outside the portal
Records a wet-ink or externally signed quote, APPROVED or SENT: the operator vouches for a signature that happened on paper. An APPROVED quote must still offer the content it was cleared for. The uploaded signed copy is REQUIRED — POST it to /v1/files with owner_kind=quote and category=uploaded_signed_copy first — and becomes the completed envelope's executed document, because for a paper signature the document presented and the document executed are the same piece of paper. Any live signature request is withdrawn first, so the buyer cannot also accept in the portal. The result reports operator provenance rather than rendering identically to an OTP-verified signature.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Record a signature made outside the portal › Request Body
executed_file_idThe uploaded signed copy, from POST /v1/files with owner_kind=quote and category=uploaded_signed_copy.
signer_nameWho signed the paper copy.
signer_emailTheir email, if known. Defaults to the customer's.
Record a signature made outside the portal › Responses
OK
The signing page for the person who signs for your organisation
The buyer page's payload (PublicQuotePageResponse) for the person who signs the offer for your organisation, with viewer org_signatory: the same document, document.model.requirements narrowed to signer_name, signer_role and consent, signing_documents as the organisation's slot sees them (its own fields to fill, the buyer's shown), and the prefill from what this person saved (PUT .../org-signing/draft), else their own name. Sign with POST /quotes/{id}/signature/countersign; the PDF is GET /quotes/{id}/buyer-page/signing-document. 409 SIGNING_COUNTERSIGN_NOT_READY while nothing is owed by your organisation, 409 SIGNING_COUNTERSIGN_AT_VENDOR when a signature provider hosts the request, 403 SIGNING_NOT_COUNTERSIGNER when somebody else is to sign. Needs quotes.sign_for_org and a signed-in person.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
query Parameters
localeThe language to show the page in; omitted, the page's own cascade decides (the offer's language, the customer's, the organization default).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
The signing page for the person who signs for your organisation › Responses
OK
Save the organisation signer's form as it stands
Keeps what the person signing for your organisation did so far — their name, role, the fields applied or filled and the adopted signature — so they can stop and resume. Only their own fields are kept; a save that holds nothing removes what was saved. Nothing is signed. Refused like GET /quotes/{id}/org-signing.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Save the organisation signer's form as it stands › Request Body
The signature the signer adopted so far.
The intake as typed so far: billing and shipping address, VAT id, and the answers to the custom fields the offer asks for (answers to anything else are dropped). Nothing here is checked against the offer's requirements; signing does that.
The signer's own fields in signing_documents as they stand, keyed by field id: true for a signature or initials field they applied or a checkbox they ticked, the text of a text field. Other signers' fields, date fields and values of the wrong type are dropped, not refused. An applied field is not a signature.
signer_nameThe name the signer has typed.
signer_roleThe role or title the signer has typed.
Save the organisation signer's form as it stands › Responses
No Content
Start the organisation signer's form over
Drops what the person signing for your organisation saved. 204, also when nothing was saved.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Start the organisation signer's form over › Responses
No Content
Where a quote stands and what it needs
The quote page's hub: the offer's process (draft, approval when the quote.send checkpoint applies to it, sent, signed, active), the one act to do next, and — while the quote is DRAFT or APPROVED — what the send checks. Every checklist item runs the send's own check without sending: a blocking item carries the exact error code the send would answer with.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Where a quote stands and what it needs › Responses
OK
Download the quote proposal PDF
Renders the quote proposal PDF on demand (org header, customer block, priced lines, totals, note, contract terms and clause snapshots, validity line and signature block; labels follow the customer's locale, de/en) and streams it as quote-
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Download the quote proposal PDF › Responses
OK
Create the quote's read-only preview link
Creates a link that shows the offer exactly as its buyer sees it, for someone who must read it without a login (a manager, a lawyer) — and can do nothing else: it cannot sign, decline or save, every write answers 403 QUOTE_PREVIEW_READ_ONLY, and opening it records no view. The URL is returned once; only its digest is stored. It works for 7 days and replaces the quote's previous preview link, which stops working. The customer's own link is not touched. Audited (quote.preview_link_created). 409 QUOTE_INVALID_TRANSITION on a voided quote.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create the quote's read-only preview link › Responses
Created
Resend (remind) a sent quote
Records a reminder nudge on a live buyer-facing quote (SENT); no status change.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Resend (remind) a sent quote › Responses
OK
Revise a declined or expired quote
Reopens a DECLINED/EXPIRED quote for editing: back to DRAFT. What was frozen at the last send (the offer, its document layout and its tax) is cleared, and the signature request behind it is withdrawn; the next send freezes and issues fresh ones. The buyer's old link is already dead: the decline or the expiry closed it.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Revise a declined or expired quote › Responses
OK
List the subscriptions this offer acts on
Returns one entry per subscription the quote touches, in the order the offer presents them, each with its draft revision's phases and every value resolved through the ladder — the rung says whether the deal stated it, carried it from an earlier phase, took it from the catalog or from the subscription's own default. A renegotiation also carries the live revision it is offered against.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the subscriptions this offer acts on › Responses
OK
Put a subscription on this offer
Adds one draft revision to the quote: a NEW subscription (minted in DRAFT and activated when the offer is signed), or a RENEGOTIATION of an existing one (its live revision is cut at the given instant and the follow-on is what the offer holds). The phases start empty and are authored on the subscription's own revision routes; an offer holding an empty revision cannot be signed. Allowed while the offer's deals may change (actions.edit.deals): on a DRAFT, and on a PENDING_APPROVAL or APPROVED quote, which goes back to DRAFT with it (its clearance was for other content; a pending approval is cancelled). Refused with 409 QUOTE_REVISIONS_LOCKED otherwise.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Put a subscription on this offer › Request Body
kindWhat this offer does to the subscription: create it (new), or cut its live revision and offer the follow-on (renegotiation).
adopt_draftBind the subscription's open draft to this offer as it is, instead of cutting the live revision or minting an empty subscription. Renegotiation: refused with cut_at. New: needs subscription_id naming a subscription that was never activated.
cut_atWhen the renegotiation takes effect. Omit for now.
nameName for the subscription this offer creates. Ignored when renegotiating.
subscription_idThe subscription being renegotiated, or the never-activated one a new offer adopts. Required for kind=renegotiation and for kind=new with adopt_draft, refused otherwise.
Put a subscription on this offer › Responses
Created
Take a subscription off this offer
Removes the binding AND discards the draft revision it was holding — both, because a draft left behind would sit on a subscription nobody offered. On a PENDING_APPROVAL or APPROVED quote it takes the quote back to DRAFT and cancels a pending approval; refused with 409 QUOTE_REVISIONS_LOCKED once the offer is out with the buyer or closed.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
subscription_idThe subscription to take off the offer.
query Parameters
reasonWhy it leaves the offer, as the quote's audit trail records it: removed (the operator took it off) or add_rolled_back (an add that could not be completed is taken back).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Take a subscription off this offer › Responses
No Content
Reissue the buyer's signing link
Withdraws the live signature request (CANCELLED, reason SUPERSEDED, every signer's link dead) and issues a replacement over a freshly frozen document, without touching the quote's lifecycle. Use it after a leak: the leaked link stops working the instant the cancel commits, and the intended recipient is re-notified with a working one. Only a SENT quote has a link to reissue (409 QUOTE_INVALID_TRANSITION otherwise); refused once anybody has signed.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Reissue the buyer's signing link › Responses
OK
Send a quote to the buyer
Releases the quote to the buyer (DRAFT or APPROVED → SENT). A quote that can still enter approval passes the quote.send checkpoint first: when it gates, the quote lands in PENDING_APPROVAL, nothing is sent, and the call answers 202 with the approval request id — the same ApprovalPending body every other gated operation answers with. An APPROVED quote is already past the checkpoint and sends without raising a second request — while it still offers the content it was cleared for; otherwise it goes back to DRAFT and the call answers 409 QUOTE_INVALID_TRANSITION. A quote whose signature_mode is EXTERNAL (a legacy value no longer written) is never sent for signature (409 QUOTE_INVALID_TRANSITION, nothing written): it is signed on paper and recorded with mark-signed. A quote signed with an emailed code (OTP) is not sent while this workspace cannot mail the code — mail switched off, or no usable sending account: 409 QUOTE_OTP_UNDELIVERABLE, nothing written. The request goes through the organisation's signing connection (its enabled default connection, else the built-in signing page), and an offer that connection cannot carry is refused before anything is written: 409 QUOTE_INTAKE_NOT_COLLECTABLE when the offer asks the buyer for something (a VAT id, a billing address not on file, a shipping address, a payment method, a custom field) that only Kontier's own signing page collects and the provider signs on its own page, naming the requirements; 422 SIGNING_PROVIDER_UNSUPPORTED when the provider cannot use the quote's signature mode or the countersignature this send would carry. With the checkpoint enabled, an API-key caller is refused 409 APPROVAL_REQUIRED_HUMAN rather than parked.
The send reads the QUOTE's signing terms, set on POST/PATCH /quotes until it is sent: who signs and is copied (signer_contact_id, copy_contact_ids; when no signer is named, the customer's Quotes & contracts contacts, else its email), the reminder cadence, the countersignature (countersign, countersigner_user_id, countersign_order) and the one deadline, expires_at. Send {} or no body. A refusal names the quote's field: 422 on countersigner_user_id when the named member has left or may not sign for the organisation, 422 on signer_contact_id / copy_contact_ids when a named contact is no longer the customer's. The body's fields are deprecated (sunset 2026-11-30) and, until then, override the quote's terms for this request.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Send a quote to the buyer › Request Body
countersignOverrides the quote's countersign for this request. Deprecated: use countersign on the quote instead. Removed on 2026-11-30.
Requests also accept the new spelling: each value in lower case (none for NONE). The listed spelling is deprecated in requests and accepted until 2026-11-30.
Overrides the quote's countersigner under PERSON. Deprecated: use countersigner_user_id on the quote instead. Removed on 2026-11-30.
expires_atNarrows the offer's own expires_at at the send; a later date is ignored. Deprecated: use expires_at on the quote instead. Removed on 2026-11-30.
Who to send to; the first entry signs, the others are copied. Overrides the quote's signer_contact_id and copy_contact_ids. Deprecated: use signer_contact_id and copy_contact_ids on the quote instead. Removed on 2026-11-30.
reminder_every_daysOverrides the quote's reminder cadence for this request. Deprecated: use reminder_every_days on the quote instead. Removed on 2026-11-30.
reminder_maxOverrides the quote's reminder cap for this request. Deprecated: use reminder_max on the quote instead. Removed on 2026-11-30.
Send a quote to the buyer › Responses
OK
Outcome-dependent: the QuoteDTO (status SENT) on 200, when the quote.send checkpoint did not gate; the ApprovalPendingDTO on 202, when it did and the quote is parked in PENDING_APPROVAL awaiting a decision.
Ask whether a sent quote can still be signed
For a SENT quote whose deadline has not passed, runs the buyer's signature as a rehearsal (rolled back) and answers whether it would go through; when it would not, names the refusal — its code, and the subscription, phase and product it is about. Something the offer depends on can change after it was sent (the renegotiated subscription cancelled or paused, a followed catalog version, an archived product). A refusal is also recorded on the quote's timeline as SIGNABILITY_LOST, at most once per send and refusal code. Every other quote answers signable.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Ask whether a sent quote can still be signed › Responses
OK
Sign for your organisation
Records your organisation's own signature on an offer the counterparty has already signed, when the request was released with a named person countersigning. No code is sent: you are signed in, and the session is the identity the record carries, alongside your user id. Refused with 409 SIGNING_COUNTERSIGN_NOT_READY before every party has signed, with 409 SIGNING_COUNTERSIGN_AT_VENDOR when a signature provider hosts the request (sign for the organisation there, with the link it mailed), and with 403 SIGNING_NOT_COUNTERSIGNER when the request names somebody else — the signed copy states who signed for the organisation, so the named person is a fact of the request rather than a role anybody with the permission may fill. Signing a second time is a no-op that answers with the request as it stands. A company seal is never countersigned here: it is applied automatically in the same instant as the counterparty's signature.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Sign for your organisation › Request Body
consentAcceptance of the signing wording shown before the action. Must be true.
The signature you adopted: the name drawn into your signature fields and your initials. The name defaults to name.
What you did with the offer's fields for your company, keyed by field id: true for a signature or initials field you applied, a string for text, true or false for a checkbox. Date fields take no value. A required field left out is refused. Refusals are 400 VALIDATION on field_values.
localeBCP-47 locale of the wording that was displayed. Defaults to the organisation's.
nameThe name signed under. Defaults to the name on the request.
roleYour role or title (e.g. Geschäftsführerin), printed beside your name on the signed copy.
Sign for your organisation › Responses
OK
Decline to sign for your organisation
Your organisation refuses to sign an offer the counterparty has signed: the request is declined with your reason (signing.signer_declined, role COUNTERSIGNER), the offer is declined as a buyer's refusal declines it, and its owner is told (quote.declined). Only while the offer does not yet count as signed — when your organisation waits for its own signature before provisioning; once the buyer's signature made it SIGNED, 409 QUOTE_SIGNED_ORG_CANNOT_DECLINE (hand your signature to somebody else instead). The same person rules as countersigning: 403 SIGNING_NOT_COUNTERSIGNER, 409 SIGNING_COUNTERSIGN_NOT_READY, 409 SIGNING_COUNTERSIGN_AT_VENDOR. Needs quotes.sign_for_org and a signed-in person.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Decline to sign for your organisation › Request Body
reasonWhy your organisation does not sign. Recorded on the request's chronology and told to the offer's owner.
Decline to sign for your organisation › Responses
OK
Change who signs for your organisation
Hands the organisation's signature on the offer's live request to another member (user_id, who must hold quotes.sign_for_org), or to anyone who may sign for the organisation (user_id null; the request is then addressed to you). Allowed until your organisation has signed; the request is mailed to the new person when the signature is already owed, and the change is recorded on the request's chronology (COUNTERSIGNER_REASSIGNED) and audited (signing.countersigner_reassigned). Needs quotes.sign_for_org and a signed-in person. 409 SIGNING_COUNTERSIGN_NOT_OWED when the request owes no signature by your organisation, 409 SIGNING_COUNTERSIGN_AT_VENDOR when a signature provider hosts it, 400 VALIDATION on user_id when the person is not a member or may not sign for the organisation.
Required scope: quotes.sign_for_org (Sign for the organization).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Change who signs for your organisation › Request Body
user_idThe member who signs for the organisation now; they must hold quotes.sign_for_org. null: anyone who may sign for the organisation.
Change who signs for your organisation › Responses
OK
Download the signed record
Streams the signature request's own artefact: the evidence record — who signed, when, from where, having accepted what wording — or, when none was produced, the executed document. Unlike /quotes/{id}/pdf (which renders the quote's CURRENT state on every call) these are fixed bytes, stored once. 404 while the quote has no completed signature request. Two digests travel on the response and they are not the same number: X-Document-Hash is the SHA-256 of the bytes in THIS body, which is what to compare a saved copy of the download against; X-Presented-Document-Hash is the SHA-256 the envelope froze over the document it PRESENTED at send, which is what to compare a copy of the offer against. Either header is omitted when the digest is not on record.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Download the signed record › Responses
The archived signed record.
Download the signed document
Streams the executed document of the quote's signature request: the pages the signers were shown, with what each entered stamped into their fields, followed by the signature record. This is the signed contract the customer keeps; /quotes/{id}/signature/document serves the evidence record. 409 SIGNING_EXECUTED_NOT_READY (with Retry-After) while every party has signed and the document is still being produced; 404 when no signature request completed. X-Document-Hash is the SHA-256 of this body; X-Presented-Document-Hash the digest the envelope froze over the presented document.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Download the signed document › Responses
The executed document.
Withdraw the offer's signature request
Takes the offer off the table without killing it: the live signature request is cancelled with the stated reason, every signing link stops working immediately, and the quote returns to APPROVED - ready to be sent again once whatever prompted the withdrawal is fixed - while it still offers the content it was cleared for; an offer amended since goes back to DRAFT and is cleared again. It is deliberately not Void, which ends the offer. Refused with 409 SIGNING_CANCEL_AFTER_SIGNATURE once anybody has signed: a request holding a signature is still live, and withdrawing one to record another signature over the top is precisely what that refusal exists to prevent. 404 when the offer has no live request.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Withdraw the offer's signature request › Request Body
reasonWhy the request is being withdrawn. Recorded on the request's chronology; not sent to the buyer.
Withdraw the offer's signature request › Responses
OK
The offer's signature request, in full
Everything the Signing surface shows: the request itself (its parties, how each one's identity is being established, where each stands, and the digest of the document they were shown), its chronology oldest first, and what may be done to it now. A quote that has never been sent for signature answers 200 with no request, an empty chronology and the capabilities of an unsent offer - not 404, because the surface is reachable in every state and has to say something in all of them. The capabilities are computed from the same rules the write paths enforce, so a control this read offers is a control the server will accept: can_withdraw in particular is false once anybody has signed, which no status value on its own reveals.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
The offer's signature request, in full › Responses
OK
What the organization's signing provider can do for this quote
The provider this quote would be signed with — the organization's enabled default signing connection, else the built-in provider — what it declares it can do (authentication levels, countersignatures, whether it reports status back), and what this quote asks the buyer that the provider's own signing page could not collect. A send that the answer rules out is refused with the same reason (SIGNING_PROVIDER_UNSUPPORTED, QUOTE_INTAKE_NOT_COLLECTABLE).
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
What the organization's signing provider can do for this quote › Responses
OK
Get the signature fields placed on the quote's document
Renders the quote's draft document (the bytes GET /quotes/{id}/pdf streams), measures its pages, and returns the fields an operator placed on them (manual), the fields the document draws itself (auto: the acceptance block's, or the appended signature page's), the fingerprint of the pages, and a summary over the offer and every shared PDF attachment and contract.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get the signature fields placed on the quote's document › Responses
OK
Save the signature fields placed on the quote's document
Replaces the operator's fields on the quote's pages. Boxes are moved into the visible page; a box smaller than its kind's minimum is refused. Send back updated_at and fingerprint as read: a layout saved since answers 409 CONFLICT, a render whose pages changed answers 409 SIGNING_LAYOUT_STALE (reload, keep nothing). A content edit: a cleared quote goes back to DRAFT; a sent one answers 409 SIGNING_LAYOUT_LOCKED.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Save the signature fields placed on the quote's document › Request Body
The operator's whole field list on the quote's pages; it replaces the saved one. Auto fields are not sent.
fingerprintThe fingerprint you read. Fields placed on a render whose pages changed since answer 409 SIGNING_LAYOUT_STALE.
updated_atThe updated_at you read; null or absent for the first save. A layout saved since answers 409 CONFLICT.
Save the signature fields placed on the quote's document › Responses
OK
Place the buyer's signature automatically
Places the buyer's default signature field: on the layout's acceptance block when it draws one (then nothing changes), else on a signature page appended at the end of the quote's document, which the draft PDF, this layout and the frozen copy carry from then on. Returns the layout. 409 SIGNING_LAYOUT_LOCKED once the quote has been sent.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Place the buyer's signature automatically › Responses
OK
Read the offer as it was sent
Returns the resolved phases, lines and values frozen when the quote was sent, together with the co-termination effects the offer carries. On a renegotiation every changed value also carries what it was. Empty before the first send and empty again after a revise, which clears the freeze.
Required scope: quotes.read (Read quotes).
path Parameters
idQuote UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Read the offer as it was sent › Responses
OK
Submit a quote for approval
Runs the quote.send approval checkpoint explicitly. When the checkpoint is enabled for this workspace and the quote clears its threshold, the quote lands in PENDING_APPROVAL and the call answers 202 with the approval request id; otherwise the operator's own authority clears it outright (DRAFT → APPROVED) and the call answers 200 with the approved quote. Either way the quote is cleared for the content it has now: a later edit of that content takes it back to DRAFT. With the checkpoint enabled, an API-key caller is refused 409 APPROVAL_REQUIRED_HUMAN rather than parked.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Submit a quote for approval › Responses
OK
Outcome-dependent: the QuoteDTO (status APPROVED) on 200, when the quote.send checkpoint did not gate; the ApprovalPendingDTO on 202, when it did and the quote is parked in PENDING_APPROVAL awaiting a decision.
Void a quote
Voids any non-terminal quote. VOIDED is terminal. Its live signature request is withdrawn first (refused with 409 SIGNING_CANCEL_AFTER_SIGNATURE once the buyer has signed it) and a pending approval request is cancelled with it, so no reminder or later approval reaches an offer that is gone.
Required scope: quotes.write (Write quotes).
path Parameters
idQuote UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Void a quote › Responses
OK