API reference
API: Quotes
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/cpq/billing | Billing systems for signed quotes (NetSuite, Metronome, Stripe): connected, on, status and settings; never credentials (owners) | integrations:write |
| POST | /v1/cpq/billing-pushes/:id/cancel | Withdraw a billing write still waiting for approval (whoever asked, or an owner) | deals:write |
| 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) | deals:write |
| POST | /v1/cpq/billing-pushes/:id/refresh | Read a written quote's billing state now (orders, invoices, payments, subscription or contract); read only | deals:write |
| DELETE | /v1/cpq/billing/:vendor | Remove a billing system's credentials and turn it off (owners) | integrations:write |
| 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) | integrations:write |
| POST | /v1/cpq/billing/:vendor/check | Check a billing system's saved credentials with one read (owners) | integrations:write |
| GET | /v1/cpq/catalog | Products and their current prices | deals:read |
| 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) | settings:write |
| 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) | settings:write |
| 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) | settings:write |
| POST | /v1/cpq/contract-periods/:id/close | Close a period: overage past the credits, and the unused share rolled into the next (owners) | settings:write |
| GET | /v1/cpq/contracts | Contracts from signed quotes | deals:read |
| GET | /v1/cpq/contracts/:id | A contract with its periods: committed, credits granted, rolled in, used, overage and rolled out | deals:read |
| POST | /v1/cpq/contracts/:id/usage | Record usage against a contract line (an integration, or a person) | deals:write |
| GET | /v1/cpq/documents/:id | Download a stored document; its SHA-256 is checked before it's returned | deals:read |
| GET | /v1/cpq/drafts | Your open drafts | deals:read |
| GET | /v1/cpq/drafts/:id | A draft with its source quotes, confidence and preview | deals:read |
| 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 | deals:write |
| POST | /v1/cpq/drafts/:id/discard | Discard a draft | deals:write |
| 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 | deals:write |
| POST | /v1/cpq/drafts/structure | Propose a deal structure (commit, ramp, expected usage) from the deal's calls and comparable won quotes | deals:write |
| DELETE | /v1/cpq/esign | Disconnect Documenso (owners) | integrations:write |
| GET | /v1/cpq/esign | Whether Documenso is connected (owners) | integrations:write |
| PUT | /v1/cpq/esign | Connect Documenso (cloud or self-hosted): API URL, token and webhook secret, stored encrypted (owners) | integrations:write |
| GET | /v1/cpq/intel | Pricing intelligence: win rate by discount band, margin trend, competitors named on the deal and how deals against them ended | deals:read |
| DELETE | /v1/cpq/links/:id | Revoke a tracked link | deals:write |
| GET | /v1/cpq/pipeline | Open quotes: count, value, age, expiry, buyer activity and follow-up state, with who to chase next and why | deals:read |
| PATCH | /v1/cpq/prices/:id | Offer or withdraw a price (owners) | settings:write |
| POST | /v1/cpq/prices/:id/versions | Change a price: saves its next version (the old one stays, for the quotes priced with it) (owners) | settings:write |
| POST | /v1/cpq/products | Add a product (owners) | settings:write |
| PATCH | /v1/cpq/products/:id | Change a product (owners) | settings:write |
| POST | /v1/cpq/products/:id/prices | Add a price to a product (owners) | settings:write |
| GET | /v1/cpq/quotes | Quotes, newest change first | deals:read |
| POST | /v1/cpq/quotes | Create a quote on a deal; it's priced at once and every number carries its evidence | deals:write |
| GET | /v1/cpq/quotes/:id | A quote: lines, every number with its evidence and formula, rules that apply, approvals and versions | deals:read |
| PATCH | /v1/cpq/quotes/:id | Change a quote (send the version you saw); a change to its prices makes earlier approvals stale | deals:write |
| 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) | deals:write |
| GET | /v1/cpq/quotes/:id/approver-context | What an approver sees: rules that fired, totals, versions, earlier decisions, and this buyer's past quotes | deals:read |
| 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 | deals:read |
| 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 | deals:write |
| 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) | deals:read |
| 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 | deals:write |
| 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 | deals:write |
| POST | /v1/cpq/quotes/:id/derive | A renewal, amendment, expansion or cancellation quote from a signed one (renewals from live usage; amendments co-terminate) | deals:write |
| GET | /v1/cpq/quotes/:id/documents | The quote's stored documents (order forms and signed copies) with their hashes | deals:read |
| 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 | deals:write |
| GET | /v1/cpq/quotes/:id/followups | The quote's follow-up cadence: each step, when it's due, and what happened | deals:read |
| POST | /v1/cpq/quotes/:id/followups/stop | Stop the quote's follow-ups | deals:write |
| GET | /v1/cpq/quotes/:id/links | The quote's tracked links | deals:read |
| POST | /v1/cpq/quotes/:id/links | A tracked link to the quote's web view for one recipient (the URL is shown once) | deals:write |
| POST | /v1/cpq/quotes/:id/signature | Send the approved quote's order form for signature (signers default to the deal's contacts) | messages:send |
| GET | /v1/cpq/quotes/:id/signatures | Signature requests for the quote, with their status and events | deals:read |
| 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 | deals:write |
| POST | /v1/cpq/quotes/:id/status | Mark a quote sent, lost or cancelled (a person, from the app or their key) | deals:write |
| GET | /v1/cpq/quotes/:id/views | What buyers read: opens per recipient, first and last open, time per section and the section read most | deals:read |
| POST | /v1/cpq/replay | Re-price recent quotes with today's prices and rules, showing what would change (owners) | settings:write |
| GET | /v1/cpq/rules | Pricing guardrails and approval rules (a starting set is added the first time) | deals:read |
| POST | /v1/cpq/rules | Add a rule (owners); refused when the check finds an error | settings:write |
| PUT | /v1/cpq/rules/:id | Change a rule (owners); approvals given under its earlier version no longer count, so open quotes ask again | settings:write |
| 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) | settings:write |
| POST | /v1/cpq/rules/draft | Draft pricing rules from a policy in plain language, checked for conflicts with test quotes and replay (owners) | settings:write |
| GET | /v1/cpq/settings | Quoting settings: the order form's seller block and default terms, and the follow-up cadence | deals:read |
| PUT | /v1/cpq/settings | Change 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();DELETE /v1/cpq/links/$ID
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();GET /v1/cpq/quotes/$ID/links
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.