Quickstart
Go from zero to your first deal in 5 minutes. Create an API key, embed the widget, and start closing deals.
Step 1: Create an API Key
Sign in to your Salesbooth account, navigate to Developers → API Keys, and create a new key.
Recommended scopes for a typical integration
Select only the scopes your integration needs. Start with these for a basic CPQ flow:
| Scope | Why you need it |
|---|---|
products:read | List and retrieve products for the widget |
deals:write | Create deals when customers complete checkout |
customers:write | Create or look up customer records |
webhooks:read | Receive deal lifecycle events |
Prefix your key with sb_test_ for sandbox mode. Sandbox deals don't charge real payment methods and can be reset at any time from Developers → Sandbox.
Your API key looks like this:
sb_test_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4Never expose your API key in client-side JavaScript. Use it only in server-side code or as a publishable key (read-only, prefixed sb_pub_) for the widget.
Step 2: Install the SDK
Choose your integration method:
<!-- Add to your HTML <head> -->
<script src="https://salesbooth.com/sdk/v1/salesbooth-widget.js"></script>npm install @salesbooth/node// ES Module
import { SalesBooth } from '@salesbooth/node';
const sb = new SalesBooth({ apiKey: 'sb_test_...' });pip install salesboothimport salesbooth
client = salesbooth.SalesBooth(api_key="sb_test_...")# No installation needed — use curl directly
export SB_API_KEY="sb_test_..."
export SB_BASE="https://salesbooth.com/api/v1"Step 3: Create Your First Product
Products are what your customers buy. Create one via the API or the Salesbooth dashboard.
curl -X POST https://salesbooth.com/api/v1/products \
-H "Authorization: Bearer $SB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Professional Plan",
"description": "Full-featured plan for growing teams",
"price": 99.00,
"price_type": "once_off"
}'# Response
{
"error": false,
"success": true,
"data": {
"product": {
"product_id": "prod_a1b2c3d4",
"version": 1,
"name": "Professional Plan",
"price": 99.00,
"price_type": "once_off",
"status": "active",
"created_at": "2026-03-09T10:30:00Z"
}
}
}const { SalesBooth } = require('@salesbooth/node');
const sb = new SalesBooth({ apiKey: 'sb_test_...' });
const product = await sb.products.create({
name: 'Professional Plan',
description: 'Full-featured plan for growing teams',
price: 99.00,
price_type: 'once_off'
});
console.log('Product created:', product.product_id); // prod_a1b2c3d4import salesbooth
client = salesbooth.SalesBooth(api_key="sb_test_...")
product = client.products.create(
name="Professional Plan",
description="Full-featured plan for growing teams",
price=99.00,
price_type="once_off"
)
print("Product created:", product.product_id) # prod_a1b2c3d4You'll use the product ID (prod_a1b2c3d4) to configure the widget in the next step.
Step 4: Embed the Deal Widget
The <salesbooth-deal> web component handles the entire deal flow — product selection, configuration, customer info, payment, and contract signature.
<!DOCTYPE html>
<html>
<head>
<script src="https://salesbooth.com/sdk/v1/salesbooth-widget.js"></script>
</head>
<body>
<salesbooth-deal
api-key="sb_pub_your_publishable_key"
products="prod_a1b2c3d4"
title="Get Started Today"
cta-text="Complete Purchase"
currency="USD"
></salesbooth-deal>
<script>
const widget = document.querySelector('salesbooth-deal');
widget.addEventListener('salesbooth:deal-created', (e) => {
console.log('Deal created!', e.detail);
});
</script>
</body>
</html>import { useEffect, useRef } from 'react';
import '@salesbooth/sdk'; // registers <salesbooth-deal>
export function CheckoutWidget({ productId }) {
const ref = useRef(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const handler = (e) => {
console.log('Deal created!', e.detail);
};
el.addEventListener('salesbooth:deal-created', handler);
return () => el.removeEventListener('salesbooth:deal-created', handler);
}, []);
return (
<salesbooth-deal
ref={ref}
api-key="sb_pub_your_key"
products={productId}
title="Get Started Today"
/>
);
}<template>
<salesbooth-deal
ref="widget"
api-key="sb_pub_your_key"
:products="productId"
title="Get Started Today"
@deal.created="onDealCreated"
/>
</template>
<script setup>
import '@salesbooth/sdk';
const props = defineProps(['productId']);
function onDealCreated(e) {
console.log('Deal created!', e.detail);
}
</script>Use your sb_pub_ publishable key in the widget — it's safe to expose in client-side code. It has read-only access to products and can only create deals on your behalf. Keep your sb_test_ / sb_live_ keys server-side.
Step 5: Handle Deal Events
Listen for widget events to trigger your own workflows — send confirmation emails, update your CRM, provision access, etc.
Client-side events (widget)
const widget = document.querySelector('salesbooth-deal');
// Deal completed by customer
widget.addEventListener('salesbooth:deal-created', (e) => {
const { deal_id, customer, total } = e.detail;
console.log(`Deal ${deal_id} created for ${customer.email}, total: $${total}`);
// Redirect to thank-you page, trigger analytics, etc.
});
// Deal signed (contract accepted)
widget.addEventListener('salesbooth:deal-signed', (e) => {
provisionAccess(e.detail.deal_id);
});
// Payment step reached (pre-fill analytics)
widget.addEventListener('step.payment', (e) => {
analytics.track('checkout_payment_step', e.detail);
});Server-side events (webhooks)
Configure a webhook endpoint in Developers → Webhooks to receive server-side notifications:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhooks/salesbooth', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-salesbooth-signature'];
const ts = req.headers['x-salesbooth-timestamp'];
const secret = process.env.WEBHOOK_SECRET;
// Verify signature
const signed = `${ts}.${req.body}`;
const expected = 'v1=' + crypto.createHmac('sha256', secret).update(signed).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body);
if (event.event === 'deal.created') {
console.log('New deal:', event.data.deal_id);
// Provision access, send email, etc.
}
res.json({ received: true });
});
app.listen(3000);import hmac, hashlib, time, os
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/salesbooth', methods=['POST'])
def webhook():
sig = request.headers.get('X-Salesbooth-Signature', '')
ts = request.headers.get('X-Salesbooth-Timestamp', '')
secret = os.environ['WEBHOOK_SECRET']
body = request.get_data()
# Verify signature
signed = f"{ts}.{body.decode()}"
expected = 'v1=' + hmac.new(
secret.encode(), signed.encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(sig, expected):
return jsonify({'error': 'Invalid signature'}), 401
event = request.get_json(force=True)
if event['event'] == 'deal.created':
print('New deal:', event['data']['deal_id'])
return jsonify({'received': True})<?php
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SALESBOOTH_SIGNATURE'] ?? '';
$ts = $_SERVER['HTTP_X_SALESBOOTH_TIMESTAMP'] ?? '';
$secret = getenv('WEBHOOK_SECRET');
// Verify signature
$signed = $ts . '.' . $payload;
$expected = 'v1=' . hash_hmac('sha256', $signed, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
if ($event['event'] === 'deal.created') {
error_log('New deal: ' . $event['data']['deal_id']);
}
echo json_encode(['received' => true]);See the Webhook Integration Guide for full details on signature verification, retry logic, and event types.
Scope Selection Matrix
Choose the minimum scopes for your use case to follow the principle of least privilege.
Next Steps
You've created your first integration. Here's where to go next: