TurboQuote JavaScript / TypeScript SDK
Let an agent scaffold this for you
Install the TurboDocx Quickstart Skill and let Claude Code, Cursor, Copilot, Codex, or any agent that speaks the Agent Skills standard install the SDK, wire it into your app, and write a working TurboQuote integration end-to-end.
$npx skills add TurboDocx/quickstart›/turbodocx-sdk turboquoteThe official TurboDocx TurboQuote SDK for Node.js and browser applications. Build quoting and CPQ (configure-price-quote) workflows: create and send quotes, manage line items, maintain a product and bundle catalog, apply price books, and handle the full quote lifecycle — all with zero runtime dependencies and complete TypeScript types. Available on npm as @turbodocx/sdk (same package as TurboSign and TurboWebhooks).
TurboQuote is TurboDocx's quoting and CPQ module. Quotes progress through a lifecycle: draft → pending_approval → sent → accepted / declined / voided. Each quote belongs to a company and contact, carries line items (individual products or bundles), and can optionally have a price book applied. Accepted quotes can be merged with a TurboDocx Deliverable (e.g. a contract generated from a template) and sent for e-signature through TurboSign via sendQuoteWithDeliverable.
Installation
- npm
- pnpm
- yarn
npm install @turbodocx/sdk
pnpm add @turbodocx/sdk
yarn add @turbodocx/sdk
Requirements
- Node.js 18 or higher (native
fetch) - TypeScript 4.7+ (optional, for type checking — declaration files are included)
- Zero runtime dependencies — the SDK uses only Node built-ins
Configuration
- TypeScript
- JavaScript
import { TurboQuote } from '@turbodocx/sdk';
TurboQuote.configure({
apiKey: process.env.TURBODOCX_API_KEY!,
orgId: process.env.TURBODOCX_ORG_ID, // optional — falls back to env var
});
const { TurboQuote } = require('@turbodocx/sdk');
TurboQuote.configure({
apiKey: process.env.TURBODOCX_API_KEY,
orgId: process.env.TURBODOCX_ORG_ID,
});
Unlike TurboSign, TurboQuote.configure() does not require senderEmail or senderName — quotes are not sent as signature emails. Only apiKey is required; orgId is recommended but falls back to TURBODOCX_ORG_ID. If you skip configure() entirely, the SDK auto-initialises from environment variables on the first method call.
Environment Variables
TURBODOCX_API_KEY=your_api_key_here
TURBODOCX_ORG_ID=your_org_id_here
# optional — defaults to https://api.turbodocx.com
TURBODOCX_BASE_URL=https://api.turbodocx.com
Quick Start
The most common flow: create a quote for a company and contact, add a product line item, then send it.
- TypeScript
- JavaScript
import { TurboQuote } from '@turbodocx/sdk';
import { writeFileSync } from 'node:fs';
TurboQuote.configure({
apiKey: process.env.TURBODOCX_API_KEY!,
orgId: process.env.TURBODOCX_ORG_ID,
});
// 1. Create a draft quote
const quote = await TurboQuote.createQuote({
name: 'Acme Corp — Enterprise Plan',
companyId: 'company-uuid',
contactId: 'contact-uuid',
currency: 'USD',
termDays: 30,
});
// 2. Add a product line item
await TurboQuote.addLineItems(quote.id, {
productId: 'product-uuid',
productName: 'Enterprise Licence',
unitPrice: 1200,
billingFrequency: 'annual',
quantity: 5,
});
// 3. Send the quote
const { quote: sentQuote, message } = await TurboQuote.sendQuote(quote.id, {
validUntil: '2026-07-31',
});
console.log(message); // "Quote sent successfully"
console.log(sentQuote.status); // "sent"
// 4. Download the PDF
const pdf = await TurboQuote.downloadQuotePdf(sentQuote.id);
writeFileSync('quote.pdf', Buffer.from(pdf));
const { TurboQuote } = require('@turbodocx/sdk');
const { writeFileSync } = require('fs');
TurboQuote.configure({
apiKey: process.env.TURBODOCX_API_KEY,
orgId: process.env.TURBODOCX_ORG_ID,
});
// 1. Create a draft quote
const quote = await TurboQuote.createQuote({
name: 'Acme Corp — Enterprise Plan',
companyId: 'company-uuid',
contactId: 'contact-uuid',
currency: 'USD',
termDays: 30,
});
// 2. Add a product line item
await TurboQuote.addLineItems(quote.id, {
productId: 'product-uuid',
productName: 'Enterprise Licence',
unitPrice: 1200,
billingFrequency: 'annual',
quantity: 5,
});
// 3. Send the quote
const { quote: sentQuote, message } = await TurboQuote.sendQuote(quote.id, {
validUntil: '2026-07-31',
});
console.log(message); // "Quote sent successfully"
console.log(sentQuote.status); // "sent"
// 4. Download the PDF
const pdf = await TurboQuote.downloadQuotePdf(sentQuote.id);
writeFileSync('quote.pdf', Buffer.from(pdf));
Convenience: createAndSend
createAndSend combines quote creation, line item addition, and sending into a single call.
const { quote } = await TurboQuote.createAndSend({
name: 'Acme Corp — Starter',
companyId: 'company-uuid',
contactId: 'contact-uuid',
currency: 'USD',
termDays: 30,
items: [
{ productId: null, productName: 'Setup Fee', unitPrice: 500, billingFrequency: 'one-time' },
{ productId: 'product-uuid', productName: 'Monthly Subscription', unitPrice: 99, billingFrequency: 'monthly', quantity: 10 },
],
send: { validUntil: '2026-07-31' },
});
console.log(quote.status); // "sent"
Method Reference
All methods are static on the TurboQuote class. Configure once, then call on the class directly.
Quotes
listQuotes
List quotes with optional pagination and filters. Returns totals and pipeline stats alongside results.
const { results, totalRecords, stats } = await TurboQuote.listQuotes({
limit: 20,
offset: 0,
statuses: ['draft', 'sent'], // string or string[]
companyId: 'company-uuid',
currency: 'USD',
});
// stats.total, stats.winRate, stats.monthlyRecurringRevenue, ...
createQuote
Create a new quote in draft status.
// Fixed-term quote — termDays 1–3650, no renewalPeriod (0 = one-time, -1 = auto-renewal)
const quote = await TurboQuote.createQuote({
name: 'Q3 Renewal', // required
companyId: 'company-uuid', // required
contactId: 'contact-uuid', // required
currency: 'USD', // 'USD'|'EUR'|'GBP'|'CAD'|'AUD'|'INR'
termDays: 30, // fixed term in days
validUntil: '2026-09-30',
taxRate: 8.5,
priceBookId: 'pb-uuid',
});
// Auto-renewal quote — termDays: -1 REQUIRES renewalPeriod, and renewalPeriod is ONLY valid
// when termDays is -1. Pairing renewalPeriod with a fixed term (e.g. termDays: 30) returns a 400.
const subscription = await TurboQuote.createQuote({
name: 'Annual Subscription',
companyId: 'company-uuid',
contactId: 'contact-uuid',
currency: 'USD',
termDays: -1, // -1 = auto-renewal
renewalPeriod: 'annually', // 'weekly'|'monthly'|'quarterly'|'annually'
});
getQuote
Fetch a single quote. The returned object includes a statusInfo field with transition flags (canSend, canAccept, canDecline, canVoid).
const quote = await TurboQuote.getQuote('quote-uuid');
console.log(quote.statusInfo?.canSend); // true when status is 'draft'
updateQuote
Patch any combination of quote fields. Pass null to clear nullable fields (renewalPeriod, validUntil, taxRate, priceBookId).
const updated = await TurboQuote.updateQuote('quote-uuid', {
name: 'Q3 Renewal — Revised',
taxRate: null, // clears the tax rate
});
deleteQuote
Soft-delete a quote.
const { message } = await TurboQuote.deleteQuote('quote-uuid');
duplicateQuote
Copy a quote (and its line items) into a new draft.
const copy = await TurboQuote.duplicateQuote('quote-uuid');
applyPriceBook
Apply a price book to all line items on a quote. Returns the updated quote plus counts of how many items were updated vs skipped.
const { quote, updatedCount, skippedCount, message } = await TurboQuote.applyPriceBook(
'quote-uuid',
'pricebook-uuid',
);
removePriceBook
Detach the price book from a quote (line item prices are not reverted).
const quote = await TurboQuote.removePriceBook('quote-uuid');
downloadQuotePdf
Download the quote as a PDF. Returns raw bytes as an ArrayBuffer.
const pdf = await TurboQuote.downloadQuotePdf('quote-uuid');
writeFileSync('quote.pdf', Buffer.from(pdf));
Quote Status Transitions
sendQuote
Send a draft quote to the contact. Optionally include CC recipients or set a validity deadline.
const { quote, message } = await TurboQuote.sendQuote('quote-uuid', {
validUntil: '2026-07-31',
ccEmails: ['manager@example.com'],
});
sendQuoteWithDeliverable
Send a quote paired with a TurboDocx deliverable (e.g., a contract generated from a template). The deliverable is merged before or after the quote PDF.
const { quote, message, documentId } = await TurboQuote.sendQuoteWithDeliverable(
'quote-uuid',
{
deliverableId: 'deliverable-uuid',
mergePosition: 'end', // 'beginning' | 'end'
ccEmails: ['legal@example.com'],
},
);
// documentId — TurboSign document created for the merged PDF
declineQuote
Mark a sent quote as declined (typically called on behalf of the recipient).
const quote = await TurboQuote.declineQuote('quote-uuid', {
reason: 'Budget constraints for this quarter',
});
voidQuote
Void a quote that should no longer be valid.
const quote = await TurboQuote.voidQuote('quote-uuid', {
reason: 'Superseded by revised quote #Q-102',
});
handleExpiredQuote
Handle a quote that has passed its validUntil date. Choose to void or decline it and optionally extend with a new validity date.
const quote = await TurboQuote.handleExpiredQuote('quote-uuid', {
action: 'void', // 'void' | 'decline'
reason: 'Expired — re-quoting',
newValidUntil: '2026-08-31',
});
Line Items
Line items attach products or bundles to a quote, each with a price, quantity, billing frequency, and optional discount.
listLineItems
const { results, totalRecords } = await TurboQuote.listLineItems('quote-uuid', {
limit: 50,
billingFrequency: 'monthly',
});
addLineItems
Add one or more product line items. Pass a single object or an array.
// Single item
await TurboQuote.addLineItems('quote-uuid', {
productId: 'product-uuid', // null for a custom (freeform) line item
productName: 'Professional Services',
unitPrice: 150,
billingFrequency: 'one-time',
quantity: 8,
discountPercent: 10,
discountType: 'percent',
});
// Multiple items at once
await TurboQuote.addLineItems('quote-uuid', [
{ productId: 'p1', productName: 'Licence A', unitPrice: 500, billingFrequency: 'annual' },
{ productId: 'p2', productName: 'Licence B', unitPrice: 300, billingFrequency: 'annual' },
]);