Skip to content

API reference

API: Quotes

Markdown version

MethodPathWhat it doesScope
GET/v1/cpq/billingBilling systems for signed quotes (NetSuite, Metronome, Stripe): connected, on, status and settings; never credentials (owners)integrations:write
POST/v1/cpq/billing-pushes/:id/cancelWithdraw a billing write still waiting for approval (whoever asked, or an owner)deals:write
POST/v1/cpq/billing-pushes/:id/failFail a billing write stuck running for over 15 minutes; what it had started is marked unknown for a person to check (owners)deals:write
POST/v1/cpq/billing-pushes/:id/refreshRead a written quote's billing state now (orders, invoices, payments, subscription or contract); read onlydeals:write
DELETE/v1/cpq/billing/:vendorRemove a billing system's credentials and turn it off (owners)integrations:write
PUT/v1/cpq/billing/:vendorConnect a billing system with your own account (NetSuite token-based authentication, a Metronome token; Stripe uses your Stripe connection), its mappings, and turn it on or off (owners)integrations:write
POST/v1/cpq/billing/:vendor/checkCheck a billing system's saved credentials with one read (owners)integrations:write
GET/v1/cpq/catalogProducts and their current pricesdeals:read
POST/v1/cpq/catalog/import/documentRead products and prices from an order form, contract, CRM export or call as a plan with quotes from the source (owners)settings:write
POST/v1/cpq/catalog/import/sheetRead a price sheet (.xlsx or .csv) as a plan, each value traced to its row and cell; accept entries to apply them (owners)settings:write
POST/v1/cpq/catalog/import/stripeRead products and prices from your Stripe account (read-only) as a plan; accept entries to apply them (owners)settings:write
POST/v1/cpq/contract-periods/:id/closeClose a period: overage past the credits, and the unused share rolled into the next (owners)settings:write
GET/v1/cpq/contractsContracts from signed quotesdeals:read
GET/v1/cpq/contracts/:idA contract with its periods: committed, credits granted, rolled in, used, overage and rolled outdeals:read
POST/v1/cpq/contracts/:id/usageRecord usage against a contract line (an integration, or a person)deals:write
GET/v1/cpq/documents/:idDownload a stored document; its SHA-256 is checked before it's returneddeals:read
GET/v1/cpq/draftsYour open draftsdeals:read
GET/v1/cpq/drafts/:idA draft with its source quotes, confidence and previewdeals:read
POST/v1/cpq/drafts/:id/acceptAccept a draft you reviewed: a request or structure becomes a draft quote, a change is applied, rules or catalog entries are saveddeals:write
POST/v1/cpq/drafts/:id/discardDiscard a draftdeals:write
POST/v1/cpq/drafts/from-requestRead a request for quote (pasted text, a file, an email or call) or a deal description into catalog line items, priced by the engine; held lines wait for youdeals:write
POST/v1/cpq/drafts/structurePropose a deal structure (commit, ramp, expected usage) from the deal's calls and comparable won quotesdeals:write
DELETE/v1/cpq/esignDisconnect Documenso (owners)integrations:write
GET/v1/cpq/esignWhether Documenso is connected (owners)integrations:write
PUT/v1/cpq/esignConnect Documenso (cloud or self-hosted): API URL, token and webhook secret, stored encrypted (owners)integrations:write
GET/v1/cpq/intelPricing intelligence: win rate by discount band, margin trend, competitors named on the deal and how deals against them endeddeals:read
DELETE/v1/cpq/links/:idRevoke a tracked linkdeals:write
GET/v1/cpq/pipelineOpen quotes: count, value, age, expiry, buyer activity and follow-up state, with who to chase next and whydeals:read
PATCH/v1/cpq/prices/:idOffer or withdraw a price (owners)settings:write
POST/v1/cpq/prices/:id/versionsChange a price: saves its next version (the old one stays, for the quotes priced with it) (owners)settings:write
POST/v1/cpq/productsAdd a product (owners)settings:write
PATCH/v1/cpq/products/:idChange a product (owners)settings:write
POST/v1/cpq/products/:id/pricesAdd a price to a product (owners)settings:write
GET/v1/cpq/quotesQuotes, newest change firstdeals:read
POST/v1/cpq/quotesCreate a quote on a deal; it's priced at once and every number carries its evidencedeals:write
GET/v1/cpq/quotes/:idA quote: lines, every number with its evidence and formula, rules that apply, approvals and versionsdeals:read
PATCH/v1/cpq/quotes/:idChange a quote (send the version you saw); a change to its prices makes earlier approvals staledeals:write
POST/v1/cpq/quotes/:id/approvalAsk for the approvals this quote needs (the rules decide who; with none needed it's approved at once)deals:write
GET/v1/cpq/quotes/:id/approver-contextWhat an approver sees: rules that fired, totals, versions, earlier decisions, and this buyer's past quotesdeals:read
GET/v1/cpq/quotes/:id/billingThe quote's billing writes: each request, its approval, what was written and read back, and the billing state read sincedeals:read
POST/v1/cpq/quotes/:id/billingAsk for a signed quote to be written to a billing system: an owner approves the exact plan in the inbox before anything is writtendeals:write
GET/v1/cpq/quotes/:id/billing/planWhat a signed quote writes to one billing system, line by line, and anything that stops it (the stored plan while a request is open)deals:read
POST/v1/cpq/quotes/:id/change-requestA change in plain language ("annual, start Oct 15, 15% off seats") as operations, re-priced with today's rules, for you to applydeals:write
POST/v1/cpq/quotes/:id/crm-attachmentAttach the signed order form PDF to the deal in each connected CRM (HubSpot, Salesforce), through policy, once eachdeals:write
POST/v1/cpq/quotes/:id/deriveA renewal, amendment, expansion or cancellation quote from a signed one (renewals from live usage; amendments co-terminate)deals:write
GET/v1/cpq/quotes/:id/documentsThe quote's stored documents (order forms and signed copies) with their hashesdeals:read
POST/v1/cpq/quotes/:id/documentsRender the quote's order form as a PDF (stored with its SHA-256; what's signed), a .docx, or a slide outlinedeals:write
GET/v1/cpq/quotes/:id/followupsThe quote's follow-up cadence: each step, when it's due, and what happeneddeals:read
POST/v1/cpq/quotes/:id/followups/stopStop the quote's follow-upsdeals:write
GET/v1/cpq/quotes/:id/linksThe quote's tracked linksdeals:read
POST/v1/cpq/quotes/:id/linksA tracked link to the quote's web view for one recipient (the URL is shown once)deals:write
POST/v1/cpq/quotes/:id/signatureSend the approved quote's order form for signature (signers default to the deal's contacts)messages:send
GET/v1/cpq/quotes/:id/signaturesSignature requests for the quote, with their status and eventsdeals:read
POST/v1/cpq/quotes/:id/signedWithout e-signature: upload the signed order form (PDF); the quote is signed, the deal won and onboarding handed offdeals:write
POST/v1/cpq/quotes/:id/statusMark a quote sent, lost or cancelled (a person, from the app or their key)deals:write
GET/v1/cpq/quotes/:id/viewsWhat buyers read: opens per recipient, first and last open, time per section and the section read mostdeals:read
POST/v1/cpq/replayRe-price recent quotes with today's prices and rules, showing what would change (owners)settings:write
GET/v1/cpq/rulesPricing guardrails and approval rules (a starting set is added the first time)deals:read
POST/v1/cpq/rulesAdd a rule (owners); refused when the check finds an errorsettings:write
PUT/v1/cpq/rules/:idChange a rule (owners); approvals given under its earlier version no longer count, so open quotes ask againsettings:write
POST/v1/cpq/rules/checkCheck a draft rule set without saving it: problems, test quotes at each rule's boundary, and recent quotes whose approvals would change (owners)settings:write
POST/v1/cpq/rules/draftDraft pricing rules from a policy in plain language, checked for conflicts with test quotes and replay (owners)settings:write
GET/v1/cpq/settingsQuoting settings: the order form's seller block and default terms, and the follow-up cadencedeals:read
PUT/v1/cpq/settingsChange quoting settings (owners)settings:write

Examples

GET /v1/cpq/billing

Billing systems for signed quotes (NetSuite, Metronome, Stripe): connected, on, status and settings; never credentials (owners)

curl -s "https://api.closefinch.com/v1/cpq/billing" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/billing-pushes/$ID/cancel

Withdraw a billing write still waiting for approval (whoever asked, or an owner)

curl -s -X POST "https://api.closefinch.com/v1/cpq/billing-pushes/$ID/cancel" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing-pushes/${id}/cancel`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/billing-pushes/$ID/fail

Fail a billing write stuck running for over 15 minutes; what it had started is marked unknown for a person to check (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/billing-pushes/$ID/fail" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing-pushes/${id}/fail`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/billing-pushes/$ID/refresh

Read a written quote's billing state now (orders, invoices, payments, subscription or contract); read only

curl -s -X POST "https://api.closefinch.com/v1/cpq/billing-pushes/$ID/refresh" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing-pushes/${id}/refresh`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

DELETE /v1/cpq/billing/$VENDOR

Remove a billing system's credentials and turn it off (owners)

curl -s -X DELETE "https://api.closefinch.com/v1/cpq/billing/$VENDOR" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing/${vendor}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

PUT /v1/cpq/billing/$VENDOR

Connect a billing system with your own account (NetSuite token-based authentication, a Metronome token; Stripe uses your Stripe connection), its mappings, and turn it on or off (owners)

curl -s -X PUT "https://api.closefinch.com/v1/cpq/billing/$VENDOR" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing/${vendor}`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/billing/$VENDOR/check

Check a billing system's saved credentials with one read (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/billing/$VENDOR/check" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/billing/${vendor}/check`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/catalog

Products and their current prices

curl -s "https://api.closefinch.com/v1/cpq/catalog" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/catalog`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/catalog/import/document

Read products and prices from an order form, contract, CRM export or call as a plan with quotes from the source (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/catalog/import/document" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/catalog/import/document`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/catalog/import/sheet

Read a price sheet (.xlsx or .csv) as a plan, each value traced to its row and cell; accept entries to apply them (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/catalog/import/sheet" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/catalog/import/sheet`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/catalog/import/stripe

Read products and prices from your Stripe account (read-only) as a plan; accept entries to apply them (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/catalog/import/stripe" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/catalog/import/stripe`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/contract-periods/$ID/close

Close a period: overage past the credits, and the unused share rolled into the next (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/contract-periods/$ID/close" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/contract-periods/${id}/close`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/contracts

Contracts from signed quotes

curl -s "https://api.closefinch.com/v1/cpq/contracts" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/contracts`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/contracts/$ID

A contract with its periods: committed, credits granted, rolled in, used, overage and rolled out

curl -s "https://api.closefinch.com/v1/cpq/contracts/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/contracts/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/contracts/$ID/usage

Record usage against a contract line (an integration, or a person)

curl -s -X POST "https://api.closefinch.com/v1/cpq/contracts/$ID/usage" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/contracts/${id}/usage`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/documents/$ID

Download a stored document; its SHA-256 is checked before it's returned

curl -s "https://api.closefinch.com/v1/cpq/documents/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/documents/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/drafts

Your open drafts

curl -s "https://api.closefinch.com/v1/cpq/drafts" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/drafts/$ID

A draft with its source quotes, confidence and preview

curl -s "https://api.closefinch.com/v1/cpq/drafts/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/drafts/$ID/accept

Accept a draft you reviewed: a request or structure becomes a draft quote, a change is applied, rules or catalog entries are saved

curl -s -X POST "https://api.closefinch.com/v1/cpq/drafts/$ID/accept" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts/${id}/accept`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/drafts/$ID/discard

Discard a draft

curl -s -X POST "https://api.closefinch.com/v1/cpq/drafts/$ID/discard" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts/${id}/discard`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/drafts/from-request

Read a request for quote (pasted text, a file, an email or call) or a deal description into catalog line items, priced by the engine; held lines wait for you

curl -s -X POST "https://api.closefinch.com/v1/cpq/drafts/from-request" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts/from-request`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/drafts/structure

Propose a deal structure (commit, ramp, expected usage) from the deal's calls and comparable won quotes

curl -s -X POST "https://api.closefinch.com/v1/cpq/drafts/structure" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/drafts/structure`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

DELETE /v1/cpq/esign

Disconnect Documenso (owners)

curl -s -X DELETE "https://api.closefinch.com/v1/cpq/esign" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/esign`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/esign

Whether Documenso is connected (owners)

curl -s "https://api.closefinch.com/v1/cpq/esign" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/esign`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

PUT /v1/cpq/esign

Connect Documenso (cloud or self-hosted): API URL, token and webhook secret, stored encrypted (owners)

curl -s -X PUT "https://api.closefinch.com/v1/cpq/esign" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/esign`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/intel

Pricing intelligence: win rate by discount band, margin trend, competitors named on the deal and how deals against them ended

curl -s "https://api.closefinch.com/v1/cpq/intel" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/intel`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

Revoke a tracked link

curl -s -X DELETE "https://api.closefinch.com/v1/cpq/links/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/links/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/pipeline

Open quotes: count, value, age, expiry, buyer activity and follow-up state, with who to chase next and why

curl -s "https://api.closefinch.com/v1/cpq/pipeline" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/pipeline`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

PATCH /v1/cpq/prices/$ID

Offer or withdraw a price (owners)

curl -s -X PATCH "https://api.closefinch.com/v1/cpq/prices/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/prices/${id}`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/prices/$ID/versions

Change a price: saves its next version (the old one stays, for the quotes priced with it) (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/prices/$ID/versions" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/prices/${id}/versions`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/products

Add a product (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/products" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/products`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

PATCH /v1/cpq/products/$ID

Change a product (owners)

curl -s -X PATCH "https://api.closefinch.com/v1/cpq/products/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/products/${id}`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/products/$ID/prices

Add a price to a product (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/products/$ID/prices" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/products/${id}/prices`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes

Quotes, newest change first

curl -s "https://api.closefinch.com/v1/cpq/quotes" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes

Create a quote on a deal; it's priced at once and every number carries its evidence

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID

A quote: lines, every number with its evidence and formula, rules that apply, approvals and versions

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

PATCH /v1/cpq/quotes/$ID

Change a quote (send the version you saw); a change to its prices makes earlier approvals stale

curl -s -X PATCH "https://api.closefinch.com/v1/cpq/quotes/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/approval

Ask for the approvals this quote needs (the rules decide who; with none needed it's approved at once)

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/approval" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/approval`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/approver-context

What an approver sees: rules that fired, totals, versions, earlier decisions, and this buyer's past quotes

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/approver-context" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/approver-context`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/billing

The quote's billing writes: each request, its approval, what was written and read back, and the billing state read since

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/billing" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/billing`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/billing

Ask for a signed quote to be written to a billing system: an owner approves the exact plan in the inbox before anything is written

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/billing" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/billing`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/billing/plan

What a signed quote writes to one billing system, line by line, and anything that stops it (the stored plan while a request is open)

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/billing/plan" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/billing/plan`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/change-request

A change in plain language ("annual, start Oct 15, 15% off seats") as operations, re-priced with today's rules, for you to apply

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/change-request" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/change-request`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/crm-attachment

Attach the signed order form PDF to the deal in each connected CRM (HubSpot, Salesforce), through policy, once each

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/crm-attachment" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/crm-attachment`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/derive

A renewal, amendment, expansion or cancellation quote from a signed one (renewals from live usage; amendments co-terminate)

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/derive" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/derive`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/documents

The quote's stored documents (order forms and signed copies) with their hashes

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/documents" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/documents`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/documents

Render the quote's order form as a PDF (stored with its SHA-256; what's signed), a .docx, or a slide outline

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/documents" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/documents`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/followups

The quote's follow-up cadence: each step, when it's due, and what happened

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/followups" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/followups`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/followups/stop

Stop the quote's follow-ups

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/followups/stop" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/followups/stop`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

The quote's tracked links

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/links" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/links`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/links

A tracked link to the quote's web view for one recipient (the URL is shown once)

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/links" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/links`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/signature

Send the approved quote's order form for signature (signers default to the deal's contacts)

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/signature" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/signature`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/signatures

Signature requests for the quote, with their status and events

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/signatures" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/signatures`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/signed

Without e-signature: upload the signed order form (PDF); the quote is signed, the deal won and onboarding handed off

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/signed" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/signed`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/quotes/$ID/status

Mark a quote sent, lost or cancelled (a person, from the app or their key)

curl -s -X POST "https://api.closefinch.com/v1/cpq/quotes/$ID/status" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/status`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/quotes/$ID/views

What buyers read: opens per recipient, first and last open, time per section and the section read most

curl -s "https://api.closefinch.com/v1/cpq/quotes/$ID/views" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/quotes/${id}/views`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/replay

Re-price recent quotes with today's prices and rules, showing what would change (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/replay" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/replay`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/rules

Pricing guardrails and approval rules (a starting set is added the first time)

curl -s "https://api.closefinch.com/v1/cpq/rules" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/rules`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/cpq/rules

Add a rule (owners); refused when the check finds an error

curl -s -X POST "https://api.closefinch.com/v1/cpq/rules" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/rules`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

PUT /v1/cpq/rules/$ID

Change a rule (owners); approvals given under its earlier version no longer count, so open quotes ask again

curl -s -X PUT "https://api.closefinch.com/v1/cpq/rules/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/rules/${id}`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/rules/check

Check a draft rule set without saving it: problems, test quotes at each rule's boundary, and recent quotes whose approvals would change (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/rules/check" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/rules/check`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/cpq/rules/draft

Draft pricing rules from a policy in plain language, checked for conflicts with test quotes and replay (owners)

curl -s -X POST "https://api.closefinch.com/v1/cpq/rules/draft" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/rules/draft`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/cpq/settings

Quoting settings: the order form's seller block and default terms, and the follow-up cadence

curl -s "https://api.closefinch.com/v1/cpq/settings" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/cpq/settings`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

PUT /v1/cpq/settings

Change quoting settings (owners)

curl -s -X PUT "https://api.closefinch.com/v1/cpq/settings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/cpq/settings`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

Request and response schemas: https://www.closefinch.com/openapi.json. All resources: API reference.

Send feedback

Tell us what's broken, confusing or missing on this page, or an idea. It goes to the team that builds the product.

Please don't include passwords or card numbers.
Only to reply about this. Never added to any mailing list.