Salesbooth API

Deal infrastructure for AI commerce. Build integrations, automate deal flows, and embed commerce into any surface with our REST API.

Overview

The Salesbooth API is a RESTful JSON API. All requests and responses use application/json.

Base URL
https://salesbooth.com/api/v1/

Response Format

Success (200 / 201)
{ "error": false, "success": true, "data": { ... } }
Error
{ "error": true, "code": "VALIDATION_ERROR", "category": "validation_error", "message": "Name is required", "recovery": { "action": "fix_request", "retryable": false }, "ref": "abc123", "details": { ... } }

Authentication

Authenticate requests with an API key sent as a Bearer token or via the X-API-Key header. All API keys must be sent in request headers — never in query parameters.

Bearer Token (recommended)
curl https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Alternative Header
curl https://salesbooth.com/api/v1/deals \ -H "X-API-Key: sb_test_example_key_do_not_use"

Key Types

Salesbooth issues three distinct key types. Choosing the right type for each context is important for security.

PrefixTypeEnvironmentNotes
sb_live_* Secret — live Production Keep private. Server-side only. Full API access within granted scopes.
sb_test_* Secret — test Sandbox Keep private. Server-side only. Operates against isolated sandbox data; no real money moves.
sb_pub_* Publishable Production Safe for browser embedding. Used by the <salesbooth-deal> widget. Scoped to widget operations only (products:read, customers:write, deals:write, agent:negotiate). Auto-generated when a widget config is created.

Publishable keys and widgets: When you create a widget config via POST /api/v1/widget-config, the response includes a publishable_key (sb_pub_*). Pass this as the api-key attribute on the <salesbooth-deal> element. Never use a secret key (sb_live_* or sb_test_*) in client-side code.

Security Notice: Passing secret API keys (sb_live_*, sb_test_*) via the ?api_key= query parameter is deprecated and will be rejected in a future release. Query parameters appear in server logs, browser history, and referrer headers — use header-based authentication instead.

Tenants can opt in to immediate enforcement by setting enforce_header_auth to 1 in tenant settings.

Note: Publishable keys (sb_pub_*) used by widget public endpoints (/api/v1/widget-config, /api/v1/widget-intelligence, /api/v1/ab-tests/resolve) are not affected by this deprecation. These endpoints handle ?api_key= in their own code paths, independent of the standard authentication flow, and must continue to use query parameter auth for browser-embedded widgets.

CORS

API keys can be restricted to specific origins. Set allowed_origins when creating a key to limit which domains can use it from the browser.

Scopes & Permissions

API keys are scoped to specific resources and operations. Assign only the scopes your integration needs.

ScopeDescription
*Full access — all resources, all operations
*:readRead-only access to all resources
deals:readRead deals, line items, and deal audit trail
deals:writeCreate, update, and manage deals and deal templates
deals:signSign and countersign deals
customers:readRead customer records and customer audit trail
customers:writeCreate and update customers
products:readRead products, pricing, and product audit trail
products:writeCreate and update products
contracts:readRead contracts and contract audit trail
contracts:writeCreate, sign, and manage contracts
webhooks:readList webhooks and delivery history
webhooks:writeRegister and manage webhooks
agent:*Full agent access — discover, negotiate, and execute deals
agent:discoverDiscover available deals and tenant catalogue
agent:negotiateNegotiate deal terms on behalf of a buyer
agent:executeExecute and accept deals
intelligence:readRead intelligence configuration and AI settings
intelligence:writeUpdate intelligence configuration and AI settings
billing:readRead credit balance and ledger
billing:writeTop up credits and manage billing
trust:readRead trust level and progress metrics
trust:writeWrite trust signals and submit fraud reports
staff:readRead staff members and availability
staff:writeCreate and update staff members
team:readRead team members
team:writeInvite, update, and remove team members
bookings:readRead bookings and appointments
bookings:writeCreate and manage bookings
queue:readRead job queue status and dead-letter queue
queue:writeRetry dead-lettered jobs and manage queue
audit:exportExport audit trail compliance packages
sites:readRead sites and pages
sites:writeCreate and manage sites, pages, and suggestions
delegations:readRead agent delegations
delegations:writeCreate and manage agent delegations
adminAdministrative operations — encryption rotation, cache management. Restrict to secure server-side keys only.

Rate Limiting

Salesbooth enforces a three-tier rate limiting system. Every request is checked against all three tiers simultaneously; the most restrictive limit that fires determines the response.

Tier 1 — Per-API-Key Limit

Each API key has a configurable per-minute limit (default: 1,000 req/min, sliding window). Agent keys receive a trust-level multiplier on top of the configured limit:

Trust LevelMultiplierEffective Limit (default key)
L0 — Untrusted0.5×500 req/min
L1 — Provisional1.0×1,000 req/min
L2 — Established2.0×2,000 req/min
L3 — Trusted5.0×5,000 req/min
L4 — Verified Partner10.0×10,000 req/min

Multipliers apply to agent API keys only. Regular user keys always use the configured limit unchanged. In addition, each key gets a burst allowance of 25% of its per-minute limit, refilled at 1 token per second.

Tier 2 — Per-IP Limit

Request TypeLimitWindow
Authenticated requests5,000 req/hrSliding hourly window
Unauthenticated requests100 req/hrSliding hourly window

Tier 3 — Global Circuit Breaker

A platform-wide circuit breaker fires at 50,000 req/min across all tenants. When tripped, the API returns 503 Service Unavailable (not 429) with Retry-After. This protects all tenants during traffic spikes.

Response Headers

HeaderDescription
X-RateLimit-LimitLimit for the tier that was checked (after trust multiplier)
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
X-RateLimit-PolicyWhich tier triggered the limit: global, ip, key, endpoint, or burst
X-Trust-LevelAgent key trust level (0–4), included when a trust multiplier applied
X-RateLimit-MultiplierTrust multiplier applied to the key limit (e.g. 2.0)
Retry-AfterSeconds to wait before retrying (present on 429 and 503)

HTTP Status Codes

StatusMeaningWhen to retry
429Per-key or per-IP limit exceededAfter Retry-After seconds with exponential backoff
503Global circuit breaker triggeredAfter Retry-After seconds; all tenants affected

Retry Pattern

async function callWithBackoff(fn, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const res = await fn(); if (res.status !== 429 && res.status !== 503) return res; const retryAfter = parseInt(res.headers.get('Retry-After') || '5', 10); const jitter = Math.random() * 1000; await new Promise(r => setTimeout(r, retryAfter * 1000 + jitter)); } throw new Error('Max retries exceeded'); }

MCP endpoint rate limits: The POST /api/v1/mcp endpoint shares the same per-key limit. Each JSON-RPC call (including every tools/call invocation) counts as one request. Agents that issue many tools/call requests in a single workflow session can exhaust this quota quickly — implement backoff on 429 responses and consider batching where possible.

Error Handling

The API uses standard HTTP status codes. Every error response includes a machine-readable code, a human-readable message, and a recovery object with action, retryable, and a hint.

Error code format: The code field uses one of two formats depending on the error origin:

  • Dotted lowercase (category.specific_code) — used by all typed exception classes (e.g. conflict.stale_version, billing.trust_ceiling_exceeded, validation_error.invalid_fields). This is the preferred modern format.
  • Uppercase Deprecated (SNAKE_CASE) — emitted by some legacy endpoint paths (e.g. VALIDATION_ERROR, BAD_REQUEST). These will be normalised to dotted lowercase format in a future release. Do not rely on exact code string matching for uppercase codes.

Migration guidance: Use the category field (always present and stable) for programmatic error handling instead of matching exact code strings. When the legacy uppercase codes are removed, integrations built on category will be unaffected. The stable category values are: validation_error, authentication_error, authorization_error, not_found, conflict, rate_limited, billing, transient_error, internal_error.

Error Response Format
{ "error": true, "code": "VALIDATION_ERROR", "message": "Name is required", "category": "validation_error", "recovery": { "action": "fix_request", "retryable": false, "hint": "Check the details.fields object for specific field errors." }, "details": { "fields": { "name": { "code": "required", "message": "Name is required" } } } }

Standard HTTP Errors

StatusCodeDescription
400BAD_REQUESTMissing or invalid parameters
400VALIDATION_ERRORRequest body failed validation — check details.fields
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENValid key but insufficient permissions
403INSUFFICIENT_SCOPEKey lacks required scope for this operation
403CORS_ORIGIN_DENIEDRequest origin not in key’s allowed origins
404NOT_FOUNDResource does not exist or you lack access
405METHOD_NOT_ALLOWEDHTTP method not supported for this endpoint
429RATE_LIMIT_EXCEEDEDToo many requests — check X-RateLimit-Reset header
500SERVER_ERRORInternal server error — safe to retry with backoff
503SERVICE_UNAVAILABLETransient outage or circuit breaker open — retry after recovery.retry_after_seconds

Optimistic Locking (412)

Resources that support concurrent updates use optimistic locking. The current resource version is returned in the ETag response header. To update, send the version in an If-Match header. A version mismatch returns 412 Precondition Failed with the current resource state so you can merge and retry.

Example — version conflict on PATCH deals
# First, fetch the current version curl https://salesbooth.com/api/v1/deals?id=deal_abc123 \ -H "Authorization: Bearer sb_test_example_key_do_not_use" # Response includes: ETag: W/"5" # Then update with the version curl -X PATCH "https://salesbooth.com/api/v1/deals?id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -H "If-Match: W/\"5\"" \ -d '{"title": "Updated Title"}' # If another request updated the deal first, you get: # 412 Precondition Failed # { "error": true, "code": "conflict.stale_version", "category": "conflict", # "message": "Resource has been modified by another request. Refresh and retry.", # "recovery": { "action": "refetch_and_retry", "retryable": true, # "hint": "Read the current resource version from response data, merge your changes, and retry with the new ETag." }, # "data": { <current resource state> } }

Domain-Specific Error Codes

StatusCodeDescriptionResolution
412 conflict.stale_version Optimistic locking conflict — resource was modified between your read and write Re-fetch the resource, apply your changes, and retry with the new ETag value in If-Match. The current resource state is included in the data field.
402 billing.insufficient_credit Your credit balance is too low to complete the operation Top up via POST /api/v1/credits or the dashboard, then retry. details.shortfall shows the amount needed.
402 billing.trust_ceiling_exceeded Monthly auto top-up ceiling reached for your trust level Wait until the 1st of next month, or upgrade your trust level. details.ceiling and details.monthly_used are included.
403 trust_cap_exceeded (category: authorization_error) Agent transaction cap exceeded for current trust level (L0: $0, L1: $500, L2: $5,000, L3+: unlimited) Complete more deals to earn trust score and advance to a higher trust level. details.transaction_cap shows your current limit.
403 DELEGATION_BUDGET_EXCEEDED (category: authorization_error) Proposed deal value exceeds the remaining delegation spending limit Propose a lower deal value within details.remaining_budget, or request a higher delegation limit from the authorizing tenant.
429 spending_limit_exceeded (category: rate_limited) Delegation per-transaction, daily, or monthly spending limit reached Wait for the limit to reset (recovery.retry_after_seconds = 86400). Check details.remaining_daily and details.remaining_monthly.

Retryable vs. Non-Retryable

Every error includes recovery.retryable. When true, the recovery.retry_after_seconds field tells you how long to wait before retrying. Implement exponential backoff for 503 and 429 responses.

Error Codes Reference

Complete taxonomy of all error codes returned by the API, grouped by category. Use the category field for programmatic handling — it is stable and will not change. The code field provides specific detail within a category.

Recommended pattern: Branch on category, not code. Future releases may add new code values within an existing category, but new categories will always be announced in the changelog.

Authentication Errors (401)

StatusCodeDescriptionRecovery
401authentication_error.invalid_credentialsMissing, malformed, or expired API keyVerify the Authorization: Bearer <key> header. Generate a new key if expired.
401UNAUTHORIZED LEGACYAuthentication failed (legacy format)Same as above. Prefer checking category === 'authentication_error'.

Authorization Errors (403)

StatusCodeDescriptionRecovery
403authorization_error.insufficient_scopeAPI key lacks the required scope for this operationIssue a new key with the required scope, or use a key that already has it. See Scopes.
403FORBIDDEN LEGACYAccess denied (legacy format)Check key scopes.
403INSUFFICIENT_SCOPE LEGACYInsufficient API key scopeAdd the required scope to your API key.
403CORS_ORIGIN_DENIEDRequest origin is not in the key’s allowed origins listAdd the origin to your API key’s allowed origins in the developer settings.
403trust_cap_exceededAgent transaction exceeds trust level spending cap (L0: $0, L1: $500, L2: $5 000)Complete more deals to advance trust levels, or use a higher trust-level agent.
403DELEGATION_BUDGET_EXCEEDEDDeal value exceeds remaining delegation budgetPropose a value within details.remaining_budget, or request a higher delegation limit.

Validation Errors (400)

StatusCodeDescriptionRecovery
400validation_error.invalid_fieldsOne or more fields failed validation — see details.fieldsFix each field listed in details.fields. Each entry has a code (required, invalid, too_long, etc.) and a human message.
400validation_error.bad_requestRequest is structurally invalid (missing required parameter, wrong type)Read message for specific guidance on what is missing or wrong.
400validation_error.body_too_largeRequest body exceeds the 1 MB limitReduce the request body size.
400validation_error.method_not_allowedWrong HTTP method for this endpointCheck the Allow response header for the allowed methods.
400validation_error.precondition_requiredIf-Match header is required but missingFetch the resource to get its current ETag, then include it as If-Match: W/"<n>".
413validation_error.body_too_largeRequest body exceeds maximum sizeReduce request body to under 1 MB.
405METHOD_NOT_ALLOWED LEGACYHTTP method not supportedCheck the Allow header.
428validation_error.precondition_requiredIf-Match header is required for this mutating operationInclude If-Match: W/"<version>" from a prior GET’s ETag header.

Not Found (404)

StatusCodeDescriptionRecovery
404not_foundResource does not exist, has been deleted, or belongs to another tenantVerify the ID is correct. Check that you’re using the right API key for this tenant.
404NOT_FOUND LEGACYResource not found (legacy format)Same as above.

Conflict Errors (409 / 412)

StatusCodeDescriptionRecovery
409conflict.stale_versionOptimistic lock conflict — resource was modified between your read and writeRe-fetch resource, merge changes, retry with new ETag in If-Match. Current resource state is in data.
409conflict.deal_already_closedOperation not permitted on a closed dealCreate a new deal.
409conflict.idempotency_key_reusedIdempotency key was already used with different request bodyUse a new unique idempotency key. If the original request succeeded, fetch the resource to check its state.
412conflict.stale_versionIf-Match version mismatch — someone else updated the resource firstRe-fetch resource (current state in data), merge, and retry with new ETag.

Billing Errors (402)

StatusCodeDescriptionRecovery
402billing.insufficient_creditCredit balance too low to complete the operationTop up via POST /api/v1/credits. details.shortfall shows the amount needed.
402billing.trust_ceiling_exceededMonthly auto top-up ceiling reached for your trust levelWait until the 1st of next month, or upgrade your trust level.

Rate Limiting (429)

StatusCodeDescriptionRecovery
429rate_limitedToo many requests — global rate limit exceededWait recovery.retry_after_seconds (default 60 s). Implement exponential backoff.
429RATE_LIMIT_EXCEEDED LEGACYToo many requests (legacy format)Check X-RateLimit-Reset header.
429spending_limit_exceededDelegation per-transaction, daily, or monthly limit reachedWait for limit reset. Check details.remaining_daily and details.remaining_monthly.

Server & Transient Errors (500 / 503)

StatusCodeDescriptionRecovery
500internal_errorUnexpected server error. The error ref field contains a trace ID for support.Contact support with the ref value. Safe to retry with exponential backoff if idempotent.
503transient_errorTemporary outage or circuit breaker openRetry after recovery.retry_after_seconds (default 5 s). Max 3 retries with exponential backoff.
500SERVER_ERROR LEGACYInternal error (legacy format)Same as above.

Error Handling — JavaScript (Fetch)

JavaScript
async function apiCall(path, options = {}) { const res = await fetch(`https://salesbooth.com/api/v1/${path}`, { ...options, headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json', ...(options.headers || {}), }, }); const data = await res.json(); if (data.error) { // Branch on category (stable) not code (may change) switch (data.category) { case 'authentication_error': // Refresh or prompt for re-authentication throw new Error('Authentication failed: ' + data.message); case 'authorization_error': throw new Error('Permission denied: ' + data.message); case 'validation_error': // data.details.fields has per-field errors throw new Error('Validation failed: ' + data.message); case 'not_found': throw new Error('Resource not found: ' + data.message); case 'conflict': if (data.code === 'conflict.stale_version') { // Merge data.data (current state) with your changes and retry throw new Error('Version conflict — refetch and retry'); } throw new Error('Conflict: ' + data.message); case 'rate_limited': // Retry after recovery.retry_after_seconds const retryAfter = data.recovery?.retry_after_seconds || 60; await new Promise(r => setTimeout(r, retryAfter * 1000)); return apiCall(path, options); // retry once case 'transient_error': // Short retry await new Promise(r => setTimeout(r, (data.recovery?.retry_after_seconds || 5) * 1000)); return apiCall(path, options); default: throw new Error(data.message || 'An error occurred (ref: ' + data.ref + ')'); } } return data.data; }

Error Handling — curl

curl
# All errors return a consistent JSON body: curl "https://salesbooth.com/api/v1/deals?id=nonexistent" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" # 404 response: # { # "error": true, # "code": "not_found", # "category": "not_found", # "message": "Resource not found", # "recovery": { # "action": "check_resource_id", # "retryable": false, # "hint": "Verify the resource ID exists and you have access to it." # }, # "ref": "trace_abc123" <-- include this in support requests # }

First Integration

The shortest path to a working integration. These four API calls are all you need to create a deal and collect a payment — no Intelligence API, negotiations, or webhooks required. Once this works, head to the SDK Quick Start for a more complete walkthrough.

Step 1 — Create a Product

curl -X POST https://salesbooth.com/api/v1/products \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Pro Plan", "price": 99.00, "type": "service" }' # Save the returned id: prod_xxxxx

Step 2 — Create a Customer

curl -X POST https://salesbooth.com/api/v1/customers \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Jane Smith", "email": "jane@example.com", "company": "Acme Corp" }' # Save the returned id: cust_xxxxx

Step 3 — Create a Deal and Add a Line Item

# Create the deal curl -X POST https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "title": "Pro Plan — Jane Smith", "currency": "USD", "tax_rate": 0.10 }' # Save the returned id: deal_xxxxx # Add a line item curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=add_item" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "quantity": 1, "unit_price": 99.00 }' # Transition to in_progress so the customer can pay curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=transition&status=in_progress" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Step 4 — Collect Payment

curl -X POST https://salesbooth.com/api/v1/payments?action=create-intent \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_xxxxx", "amount": 108.90, "currency": "USD" }' # Returns a Stripe client_secret — pass to Stripe.js on your frontend to complete payment

That's it. You now have a complete deal flow: product → customer → deal → payment. For embeddable widgets, AI deal scoring, webhooks, negotiations, and more, continue to the SDK Quick Start below.

SDK Quick Start

From zero to a live deal widget in 5 minutes. This walkthrough installs the SDK, creates a product, creates a deal, and embeds the deal widget on your page.

Step 1 — Install

CDN (browser)
<script src="https://salesbooth.com/sdk/v1/salesbooth.js"></script>
Node.js / CommonJS (npm)
# Install from npm npm install @salesbooth/node const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' });

Step 2 — Create a Product

const product = await sb.products.create({ name: 'Pro Plan', price: 99.00, type: 'service', description: 'Monthly pro subscription' }); console.log('Product:', product.product_id); // prod_xxxxx

Step 3 — Create a Customer & Deal

Initialize + Create a Deal
const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // Create a customer const customer = await sb.customers.create({ name: 'Jane Smith', email: 'jane@example.com', company: 'Acme Corp' }); // Create a deal with a line item const deal = await sb.deals.create({ customer_id: customer.customer_id, currency: 'USD', tax_rate: 0.10 }); await sb.deals.addItem(deal.deal_id, { product_id: 'prod_xxxxx', quantity: 1, unit_price: 499.00 }); console.log('Deal created:', deal.deal_id);

SDK Resources: The SDK exposes sb.deals, sb.customers, sb.products, sb.contracts, sb.webhooks, sb.negotiations, sb.templates, sb.intelligence, sb.delegations, sb.configuration, sb.productRules, sb.savedConfigs, sb.widgets, and sb.analytics. Each resource provides list(), get(), create(), update(), and resource-specific methods.

Step 4 — Add a Line Item & Transition

await sb.deals.addItem(deal.deal_id, { product_id: product.product_id, quantity: 1, unit_price: 99.00 }); // Move the deal from draft to in_progress await sb.deals.transition(deal.deal_id, 'in_progress'); console.log('Deal ready:', deal.deal_id);

Step 5 — Embed the Deal Widget

The deal widget lets buyers configure products, negotiate, and sign — all embedded in your site with a single script tag.

Create a widget config (server-side)
curl -X POST https://salesbooth.com/api/v1/widget-config \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "site_id": "site_xxxxx", "title": "Get Pro Plan", "currency": "USD", "products": "prod_xxxxx" }' # Response includes: { "data": { "widget_id": "wgt_xxxxx", "publishable_key": "sb_pub_xxxxx" } }
Embed in your HTML
<!-- 1. Load the widget SDK --> <script src="https://salesbooth.com/sdk/v1/salesbooth-widget.js" crossorigin="anonymous"></script> <!-- 2. Place the custom element anywhere in your page --> <salesbooth-deal api-key="sb_pub_xxxxx"></salesbooth-deal> <!-- 3. Listen for deal events --> <script> document.querySelector('salesbooth-deal').addEventListener('deal:closed', (e) => { console.log('Deal closed!', e.detail.deal_id); }); </script>

Core integration complete. Steps 1–5 cover the most common use case. The steps below show optional advanced features — you can skip them on your first integration and return when you need them.

Step 6 — Score a Deal with the Intelligence API (optional)

const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // Get AI score for a deal const score = await sb.intelligence.score('deal_abc123'); console.log(`Score: ${score.data.score}/100 (${score.data.confidence} confidence)`); // Get pricing suggestions const suggestion = await sb.intelligence.pricingSuggestion('deal_abc123'); console.log(`Suggested price: ${suggestion.data.suggested_price} (win rate: ${suggestion.data.win_rate_at_suggested})`); // Get risk assessment const risk = await sb.intelligence.risk('deal_abc123'); if (risk.data.overall_risk !== 'low') { const highRisk = risk.data.factors.filter(f => f.severity === 'high'); highRisk.forEach(f => console.warn(`Risk: ${f.factor} — ${f.mitigation}`)); } // Get pipeline forecast for next 90 days const forecast = await sb.intelligence.pipelineForecast({ period: '90d' }); console.log(`90-day weighted pipeline: $${forecast.data.weighted_pipeline.toLocaleString()}`);

Step 7 — Negotiate Deal Terms (optional)

const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // Propose terms to a merchant await sb.negotiations.propose('deal_abc123', { proposed_terms: { discount_percent: 12, payment_terms: 'net_30' }, message: 'Can we agree on 12% for a 3-year commitment?', expires_at: '2026-03-19T00:00:00Z' }); // Get AI suggestions before countering const suggestions = await sb.negotiations.suggest('deal_abc123'); const balanced = suggestions.data.suggestions.find(s => s.strategy === 'balanced'); console.log('AI suggests:', balanced.proposed_terms, `(confidence: ${balanced.confidence})`); // Counter with AI-suggested terms await sb.negotiations.counter('deal_abc123', { proposed_terms: balanced.proposed_terms, message: balanced.rationale }); // Accept the other party's latest terms await sb.negotiations.accept('deal_abc123'); // Get full negotiation history const history = await sb.negotiations.get('deal_abc123'); console.log(`${history.data.total_rounds} rounds, final status: ${history.data.status}`);

Step 8 — Set Up a Webhook Listener (optional)

const crypto = require('crypto'); const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // Register a webhook endpoint const webhook = await sb.webhooks.create({ url: 'https://myapp.com/webhooks/salesbooth', events: ['deal.closed', 'deal.payment_received', 'subscription.renewed', 'negotiation.accepted'], description: 'Production webhook' }); console.log('Webhook registered:', webhook.webhook_id); console.log('Signing secret (save this):', webhook.secret); // Verify incoming events (server-side) function verifyAndParseWebhook(rawBody, sig, timestamp, secret) { const age = Math.floor(Date.now() / 1000) - parseInt(timestamp, 10); if (age > 300) throw new Error('Stale event'); const expected = 'v1=' + crypto.createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`, 'utf8').digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) throw new Error('Invalid signature'); return JSON.parse(rawBody); } // Handle deal.closed function handleEvent(event) { switch (event.event) { case 'deal.closed': console.log(`Deal ${event.data.deal_id} closed — revenue: ${event.data.total}`); break; case 'negotiation.accepted': console.log(`Negotiation accepted: ${JSON.stringify(event.data.final_terms)}`); break; case 'subscription.renewed': console.log(`Subscription renewed: $${event.data.total_amount} ${event.data.currency}`); break; } }

Step 9 — List Products and Create a Deal (optional)

const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // List available products const products = await sb.products.list({ limit: 10 }); const product = products.products.find(p => p.name === 'Pro Plan'); console.log('Product:', product.product_id, '— price:', product.price); // Create a customer const customer = await sb.customers.create({ name: 'Jane Smith', email: 'jane@example.com', company: 'Acme Corp' }); // Create deal, add item, and transition const deal = await sb.deals.create({ customer_id: customer.customer_id, currency: 'USD', tax_rate: 0.10 }); await sb.deals.addItem(deal.deal_id, { product_id: product.product_id, quantity: 5, unit_price: product.price }); // Apply discount and transition await sb.deals.applyDiscount(deal.deal_id, { type: 'percent', value: 10 }); await sb.deals.transition(deal.deal_id, 'in_progress'); console.log(`Deal ${deal.deal_id} ready — total: $${deal.total}`);

Event Handling

sb.on('error', (err) => console.error(err.code, err.message)); sb.on('offline', () => console.log('Offline — requests will queue')); sb.on('online', () => console.log('Back online — flushing queue'));

Python Examples

The Salesbooth REST API is language-agnostic. The following examples use the requests library.

Install
pip install requests
Python — Create a customer and deal
import requests API_KEY = "sb_test_example_key_do_not_use" BASE = "https://salesbooth.com/api/v1" HDR = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} # Create a customer r = requests.post(f"{BASE}/customers", headers=HDR, json={ "name": "Jane Smith", "email": "jane@example.com", "company": "Acme Corp" }) r.raise_for_status() customer = r.json()["data"] print("Customer:", customer["id"]) # Create a deal with idempotency r = requests.post(f"{BASE}/deals", headers={**HDR, "Idempotency-Key": "order-20260317-001"}, json={ "customer_id": customer["id"], "currency": "USD", "tax_rate": 0.10 }) r.raise_for_status() deal = r.json()["data"] print("Deal:", deal["id"]) # Add a line item r = requests.post(f"{BASE}/deals?id={deal['id']}&action=add_item", headers=HDR, json={ "product_id": "prod_xxxxx", "quantity": 1, "unit_price": 499.00 }) r.raise_for_status() print("Line item added") # Transition to in_progress r = requests.post(f"{BASE}/deals?id={deal['id']}&action=transition&status=in_progress", headers=HDR) r.raise_for_status() print("Deal transitioned:", r.json()["data"]["status"])
Python — Verify a webhook signature
import hashlib, hmac, time from flask import Flask, request, abort app = Flask(__name__) WEBHOOK_SECRET = "your_webhook_signing_secret" TOLERANCE = 300 # 5 minutes @app.post("/webhooks/salesbooth") def handle_webhook(): sig = request.headers.get("X-Salesbooth-Signature", "") timestamp = request.headers.get("X-Salesbooth-Timestamp", "0") body = request.get_data() # raw bytes — do NOT parse before verifying # Replay protection: reject events older than 5 minutes if abs(time.time() - int(timestamp)) > TOLERANCE: abort(400, "Stale webhook") # HMAC-SHA256: sign timestamp.body payload = f"{timestamp}.".encode() + body expected = 'v1=' + hmac.new(WEBHOOK_SECRET.encode(), payload, hashlib.sha256).hexdigest() # Constant-time comparison if not hmac.compare_digest(sig, expected): abort(400, "Invalid signature") event = request.get_json() print(f"Event: {event['event']} id={event['id']}") return "", 200

curl Examples

curl — List deals with filters
curl "https://salesbooth.com/api/v1/deals?status=in_progress&limit=20" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
curl — Create a product
curl -X POST https://salesbooth.com/api/v1/products \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Enterprise License", "price": 4999.00, "type": "service", "description": "Annual enterprise subscription" }'
curl — Score a deal (Intelligence API)
curl "https://salesbooth.com/api/v1/intelligence?deal_id=deal_abc123&type=score" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

What’s Next

TopicJump to
Receive real-time events for deal changes, payments, and renewalsWebhooks
Let buyers propose & counter deal termsNegotiations
Build AI agents that negotiate and close deals autonomouslyAgent Integration
Grant sub-agents constrained spending authorityDelegations
Embed a configurable deal widget on your siteWidgets
Score deals and get AI pricing suggestionsIntelligence API
Configure product bundles, options, and rulesCPQ / Configuration
Full REST reference — every endpoint, parameter, and responseCore Resources

Security Best Practices

Salesbooth handles payments, contracts, and customer PII. This section explains the security controls built into the API and the patterns you should follow in your integration.

Idempotency Keys

Any POST request that creates a financial record (deal, payment intent, subscription) accepts an optional Idempotency-Key header. If a request fails in transit or you receive no response, resend the request with the same key. The server will return the original response without double-creating the resource.

Use idempotency keys for: POST /deals, POST /payments, POST /subscriptions, POST /contracts. Keys must be unique per request, 1–64 characters, and should be regenerated for genuinely new operations.

Example — Idempotent deal creation
curl -X POST https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_live_xxxxxx" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-2026-03-17-acme-0042" \ -d '{ "customer_id": "cust_xxxxx", "currency": "USD" }' # Network timeout — resend with the same key; no duplicate is created. curl -X POST https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_live_xxxxxx" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-2026-03-17-acme-0042" \ -d '{ "customer_id": "cust_xxxxx", "currency": "USD" }' # Returns HTTP 200 (not 201) with the originally-created deal.

Idempotency keys expire after 24 hours. Replies are cached so all responses, including errors, are returned as-is on a replay.

Field Whitelisting (Mass-Assignment Protection)

Every write endpoint accepts only the explicitly documented fields shown in its parameter table. Undocumented or system-controlled fields sent in the request body are silently dropped — they do not produce an error, and they are never persisted. This prevents mass-assignment attacks where a client might try to set server-managed values such as status, payment_status, tenant_id, or financial totals.

System-controlled fields that cannot be set by API clients:

  • id, tenant_id — generated by the server
  • status, payment_status, contract_status — controlled by state machine transitions, not free-form writes
  • subtotal, total, tax_amount — calculated server-side from line items
  • created_at, updated_at, signed_at, closed_at — set by the server on lifecycle events
  • version, hash_chain — used for audit integrity; never writable

To change deal status, use the action=transition action endpoint, which enforces the state machine rules. Direct status writes are rejected.

Input Validation

All inputs are validated server-side before any database write occurs. Validation errors return 400 VALIDATION_ERROR with a details.fields map indicating which fields failed and why. Client-side validation should be considered a UX improvement only — never rely on it for security.

Rule enforcedExample
Numeric rangesdeposit_pct must be 0–1; negative values or values >1 are rejected with validation_error.out_of_range
Required fieldsMissing required fields return per-field errors in details.fields
String lengthsNames max 255 chars, descriptions max 10,000 chars
Currency codesMust match ISO 4217 (e.g. USD, EUR, AUD)
Tax ratesStored as decimal(5,4); values ≥1 are treated as a percentage and normalised (e.g. 100.1000)

Distributed Transaction Semantics

Some Salesbooth operations touch multiple subsystems (deal, contract, payment, messaging). The platform uses a saga pattern with compensating transactions to handle partial failures:

  • Atomic commitment — deal creation is a single database transaction. If any part fails, the whole operation rolls back and you receive an error response. No partial deal is created.
  • Saga-based orchestration — operations that span subsystems (e.g. closing a deal triggers payment settlement, contract finalisation, and webhook delivery) use async jobs. If a downstream step fails, the system retries with exponential backoff up to 3 times. You can monitor job status via the X-Job-ID response header on long-running operations.
  • Webhook delivery guarantees — webhooks are delivered at-least-once with a 3-attempt retry. Check the dead-letter queue (GET /webhooks/dead_letter) to find undelivered events and use POST /webhooks/replay to re-deliver them.
  • Idempotency on retries — use Idempotency-Key headers so that retrying a failed request does not create duplicate records.

Data Encryption

All customer PII (names, emails, phone numbers) is encrypted at rest using per-tenant AES-256-GCM keys. Keys are rotated on a configurable schedule (default: 90 days). API responses return decrypted values to authorised callers; raw encrypted bytes are never exposed via the API.

LayerMechanism
In transitTLS 1.2+ enforced on all endpoints; HTTP is redirected to HTTPS
At rest (PII)AES-256-GCM, per-tenant key, stored in key vault separate from data
At rest (database)Full-disk encryption on all database volumes
API keysStored as bcrypt hashes; plaintext is shown only at creation time
Webhook secretsStored encrypted; only the HMAC-SHA256 signature is verifiable

PCI Compliance

Salesbooth is a PCI DSS Level 1 certified service provider. Card data is handled entirely by Stripe — raw card numbers never pass through Salesbooth servers. Salesbooth stores only Stripe PaymentIntent IDs and tokenised payment method references.

Your integration scope is reduced: Because card data flows directly from the buyer’s browser to Stripe’s hosted fields, your application only needs to satisfy SAQ A requirements (the simplest PCI assessment level) when using the Salesbooth widget. If you build a fully custom payment flow using the Salesbooth REST API directly, consult Stripe’s PCI guidance for your integration type.

Permission Boundaries

Different operations require different API key scopes, enforcing a principle of least privilege. A single key should be granted only the scopes it genuinely needs:

OperationRequired scopeNotes
Read deals / customersdeals:read / customers:readRead-only; safe for reporting integrations
Create/modify dealsdeals:writeServer-side only; never expose in browser JS
Modify contracts or templatescontracts:writeRestrict to admin-level server keys
Configure paymentsdeals:write + Stripe connectionRequires separate Stripe OAuth; finance team only
Widget / browser embeddingPublishable key (sb_pub_*)Auto-scoped to products:read, customers:write, deals:write, agent:negotiate only
Audit export / complianceaudit:exportSeparate key; never combined with write scopes

HTTPS and TLS

All API traffic must use HTTPS. HTTP requests are upgraded automatically via 301 redirect, but you should always use HTTPS in your integration from the start. The minimum TLS version accepted is TLS 1.2; TLS 1.3 is preferred. Certificate pinning is not required but your HTTP client should validate the certificate chain.

Deals

Create, manage, and transition deals through their lifecycle. Deals contain line items and support cryptographic signing and audit trails.

GET /api/v1/deals
List deals with optional filters, or retrieve a single deal by ID. Returns paginated results.
ParameterDescription
idDeal ID to retrieve a specific deal (e.g. deal_xxxxxxxxxx). When provided, returns a single deal object instead of a list.
actionAction to perform: terms (requires id), compare-terms (requires deal_id_1 & deal_id_2), audit, verify_audit, escrow, credential, valid_transitions, signing_certificate, export
deal_id_1First deal ID for compare-terms action
deal_id_2Second deal ID for compare-terms action
statusFilter: draft, in_progress, pending_signature, awaiting_signatures, pending_payment, partially_accepted, closed, cancelled, expired
customer_idFilter by customer ID
created_afterISO 8601 date filter
created_beforeISO 8601 date filter
min_valueFilter deals with total value >= this amount
max_valueFilter deals with total value <= this amount
limitMax results, 1–100 (default: 50)
offsetPagination offset (default: 0). Ignored when after/before cursors are provided.
afterCursor for forward pagination. Pass the next_cursor from a previous response.
beforeCursor for backward pagination. Pass the prev_cursor from a previous response.
sortSort field for cursor pagination: created_at (default) or updated_at
fieldsComma-separated list of fields to include in the response (e.g. id,status,total)
includeComma-separated nested resources to include (e.g. line_items,pricing,customer)
excludeComma-separated nested resources to exclude from the response
formatResponse format shortcut: minimal returns only id, status, and updated_at
GET /api/v1/deals?id={deal_id}
Retrieve a single deal with its line items and signatures.
POST /api/v1/deals
Create a new deal.
FieldTypeDescription
title requiredstringDeal title (max 255 chars)
customer_idstringCustomer identifier (omit for widget negotiations or draft deals)
descriptionstringDeal description
currencystringISO 4217 currency code (default: USD)
tax_ratenumberTax rate as decimal (e.g. 0.10 for 10%)
deal_typestringone_time (default) or recurring
billing_cyclestringmonthly, quarterly, or annual (required when deal_type is recurring)
presentation_currencystringISO 4217 currency for display (auto-converted from currency)
settlement_currencystringISO 4217 currency for settlement
statusstringInitial status (default: draft)
notesstringInternal notes (not visible to customers)
metadataobjectArbitrary key-value metadata (max depth 3)
template_idstringDeal template ID to create from (pre-populates fields from template)
Example
curl -X POST https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "title": "Enterprise License Deal", "currency": "USD", "tax_rate": 0.10 }'
Response (201)
{ "error": false, "data": { "deal_id": "deal_abc123", "version": 1, "customer_id": "cust_xxxxx", "title": "Enterprise License Deal", "status": "draft", "currency": "USD", "line_items": [], "pricing": { "currency": "USD", "tax_rate": "0.1000", "subtotal": { "amount": "0.00", "currency": "USD", "formatted": "$0.00" }, "total": { "amount": "0.00", "currency": "USD", "formatted": "$0.00" } }, "created_at": "2026-03-09T10:30:00Z", "updated_at": "2026-03-09T10:30:00Z" } }
PATCH /api/v1/deals?id={deal_id}
Update deal fields. Send only the fields you want to change. Requires an If-Match header with the current ETag version for optimistic locking.
FieldTypeDescription
customer_idstringCustomer ID to reassign this deal to
titlestringDeal title
descriptionstringDeal description
notesstringInternal notes
statusstringdraft, in_progress, pending_payment, pending_signature, partially_accepted, closed, cancelled, or expired
currencystringISO 4217 currency code (e.g. USD)
tax_ratenumberTax rate as decimal (e.g. 0.10 for 10%). Values ≥1 are automatically divided by 100 for compatibility (e.g. 100.10); prefer the decimal form.
deal_typestringone_time or recurring
billing_cyclestringmonthly, quarterly, or annual
metadataobjectArbitrary key-value metadata (max depth 3)
Example
curl -X PATCH "https://salesbooth.com/api/v1/deals?id=deal_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -H "If-Match: 3" \ -d '{ "currency": "AUD", "tax_rate": 0.10, "notes": "Updated pricing agreed in call" }'
DELETE /api/v1/deals?id={deal_id}
Cancel a deal (transitions to cancelled status). If the deal is already cancelled, it is hard-deleted. Pass action=remove_item&item_id={id} to remove a single line item instead.
Example — Cancel deal
curl -X DELETE "https://salesbooth.com/api/v1/deals?id=deal_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "If-Match: 1"
Example — Remove line item
curl -X DELETE "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=remove_item&item_id=item_yyyyy" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "If-Match: 1"

Deal Actions

POST /api/v1/deals?id={deal_id}&action=add_item
Add a line item to a deal.
FieldTypeDescription
deal_id requiredstringDeal ID
product_id requiredstringProduct to add
quantityintegerQuantity (default 1)
optionsobjectSelected configuration options
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=add_item" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_xxxxx", "product_id": "prod_xxxxx", "quantity": 2, "options": {} }'
GET /api/v1/deals/{id}/valid-transitions
Return the set of status transitions currently allowed for a deal, based on its current state and any active conditions (signing requirements, escrow holds, etc.). Use this before showing state-change UI to the user.
Example
curl "https://salesbooth.com/api/v1/deals/deal_xxxxx/valid-transitions" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal_id": "deal_xxxxx", "current_status": "in_progress", "transitions": [ { "target": "pending_signature", "available": true, "conditions": [], "action": { "method": "POST", "endpoint": "/api/v1/deals?id=deal_xxxxx&action=transition&status=pending_signature", "description": "Send for signature" } }, { "target": "cancelled", "available": true, "conditions": [], "action": { "method": "POST", "endpoint": "/api/v1/deals?id=deal_xxxxx&action=transition&status=cancelled", "description": "Cancel" } } ] } }
POST /api/v1/deals?id={deal_id}&action=transition&status={status}
Transition a deal to a new status. Valid transitions: draftin_progresspending_signaturepending_paymentclosed.
POST /api/v1/deals?id={deal_id}&action=sign
Cryptographically sign a deal. Creates a verifiable signature with hash chain.
FieldTypeDescription
signer_typestringuser, customer, agent, or api_key
signer_idstringID of the signer (optional; defaults to the authenticated identity)
signer_customer_idstringCustomer ID to sign on behalf of. Required when an API key signs a deal that belongs to a specific customer. Triggers authorization checks via the deal's customer association.
consent_to_signbooleanRequired true for human signers (user or customer)
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=sign" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"consent_to_sign": true}'
POST /api/v1/deals?id={deal_id}&action=unsign
Remove the signature from a deal, reverting it to an unsigned state. Only valid while the deal has not been closed.
FieldTypeDescription
reasonstringOptional reason for removing the signature (recorded in audit log)
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=unsign" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "Terms need revision"}'
POST /api/v1/deals?id={deal_id}&action=update_item&item_id={item_id}
Update the quantity of an existing line item on a deal. The item_id query parameter is required.
FieldTypeDescription
quantity requiredintegerNew quantity (minimum: 1)
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=update_item&item_id=item_yyyyy" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"quantity": 3}'
POST /api/v1/deals?id={deal_id}&action=apply_discount
Apply a discount to a deal. Discounts can be a fixed amount or a percentage of the deal total.
FieldTypeDescription
type requiredstringpercentage or fixed
value requirednumberDiscount value — percentage points (e.g. 10 for 10% off) or fixed currency amount
codestringOptional promo code associated with this discount
descriptionstringHuman-readable description of the discount (shown on invoice)
Example — 15% off
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=apply_discount" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "type": "percentage", "value": 15, "description": "Loyalty discount" }'
Example — $50 fixed discount
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=apply_discount" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "type": "fixed", "value": 50, "code": "SAVE50", "description": "Promotional offer" }'
POST /api/v1/deals?id={deal_id}&action=set-terms
Attach structured, machine-readable deal terms to a deal. Terms are versioned and validated against the active deal-terms schema. Once set, terms are included in the signed hash and can be verified by third parties.
FieldTypeDescription
terms requiredobjectDeal terms object. Must include terms_schema_version and payment_terms. See Deal Terms Schema for the full field reference.
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=set-terms" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "terms": { "terms_schema_version": "1.0", "payment_terms": { "type": "net", "due_date": "2026-04-30" } } }'
POST /api/v1/deals?action=create-configured
Atomically create a fully-configured deal — customer, line items, discounts, and terms — in a single request. Designed for agent workflows and integrations that need to create ready-to-sign deals without multiple round-trips. Requires the agent:execute API key scope.
FieldTypeDescription
customer_idstringExisting customer ID. Provide either customer_id or customer (inline create)
customerobjectInline customer: name, email, phone, company. Creates the customer if they don't exist (matched by email)
itemsarrayLine items array. Each item: product_id, quantity, unit_price, name, optional configuration with option_ids
saved_config_idstringSaved product configuration ID. Use instead of items to populate line items from a saved configuration
discountsarrayOptional discounts array. Each entry: type (percentage or fixed), value, description
template_idstringOptional deal template to apply default settings from
currencystringISO 4217 currency code (e.g. USD)
notesstringInternal notes
metadataobjectArbitrary key-value metadata
dry_runbooleanIf true, validates and returns the deal object without persisting it
Example
curl -X POST "https://salesbooth.com/api/v1/deals?action=create-configured" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer": { "name": "Jane Smith", "email": "jane@example.com", "company": "Acme Corp" }, "items": [ { "product_id": "prod_xxxxx", "name": "Professional Plan", "quantity": 1, "unit_price": 499.00 } ], "discounts": [ {"type": "percentage", "value": 10, "description": "First-year discount"} ], "currency": "USD" }'
POST /api/v1/deals?id={deal_id}&action=partial_accept
Accept a subset of line items from a deal, rejecting the rest. The deal transitions to partially_accepted status. Optionally creates a separate deal for the rejected items.
FieldTypeDescription
accepted_items requiredarrayArray of line item IDs to accept (at least one required)
rejected_itemsarrayArray of line item IDs being explicitly rejected (informational)
create_declined_dealbooleanIf true, create a new deal containing the rejected items for further negotiation
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=partial_accept" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "accepted_items": ["item_aaa", "item_bbb"], "rejected_items": ["item_ccc"], "create_declined_deal": true }'
POST /api/v1/deals?id={deal_id}&action=escrow
Place deal funds in escrow, pending fulfilment of one or more conditions. Funds are held until all conditions are met (triggering release_escrow) or the escrow expires/is refunded. Escrow expires after 7 days by default.
FieldTypeDescription
conditions requiredarrayArray of condition objects, each with type (e.g. delivery, approval) and optional config
amountnumberAmount to hold in escrow. Defaults to the deal total
currencystringISO 4217 currency code. Defaults to the deal currency
expires_inintegerSeconds until the escrow expires (default: 604800 / 7 days)
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=escrow" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ {"type": "delivery", "config": {"tracking_required": true}}, {"type": "approval"} ], "expires_in": 1209600 }'
POST /api/v1/deals?id={deal_id}&action=release_escrow
Release held escrow funds to the seller. All conditions must be fulfilled before release is permitted. Triggers the escrow.released webhook event and closes the deal.
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=release_escrow" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/deals?id={deal_id}&action=refund_escrow
Refund escrowed funds back to the buyer and cancel the escrow hold. Triggers the escrow.refunded webhook event.
FieldTypeDescription
reasonstringReason for refund: manual (default), condition_failed, deal_cancelled, fraud, or duplicate
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=refund_escrow" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "condition_failed"}'
POST /api/v1/deals?id={deal_id}&action=fulfill_condition
Mark a specific escrow condition as fulfilled. When all conditions on an escrow are fulfilled, the funds become releasable. Triggers the escrow.condition_fulfilled webhook event.
FieldTypeDescription
condition_id requiredstringID of the escrow condition to mark as fulfilled
met_bystringOptional identifier of the party or system that fulfilled the condition
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=fulfill_condition" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "condition_id": "cond_yyyyy", "met_by": "logistics_system" }'
POST /api/v1/deals?id={deal_id}&action=revoke_credential
Revoke the verifiable credential issued for a signed deal. The credential is added to the revocation list and can no longer be used to verify the deal. Use when a deal is disputed, superseded, or the credential is compromised.
FieldTypeDescription
reasonstringReason for revocation: manual (default), deal_cancelled, fraud, expired, or superseded
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=revoke_credential" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "superseded"}'
POST /api/v1/deals?id={deal_id}&action=record-outcome
Record the win/loss outcome of a deal for pipeline analytics and forecasting. Can include competitor information for loss analysis. Recorded outcomes feed the deal intelligence module.
FieldTypeDescription
reason requiredstringOutcome reason. Typically won, lost, no_decision, or a custom value
notesstringFree-text notes about the outcome (stored in audit log)
competitor_namestringName of the competitor chosen instead (for loss analysis)
Example — Won deal
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=record-outcome" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "won", "notes": "Closed after demo on 2026-03-28"}'
Example — Lost deal
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=record-outcome" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "reason": "lost", "notes": "Went with competitor on price", "competitor_name": "CompetitorCo" }'
POST /api/v1/deals?id={deal_id}&action=save-as-template
Save the current deal as a reusable deal template. The template captures the deal structure (line items, terms, discounts, metadata) and can be used to create new deals with the same configuration via template_id on a create request.
FieldTypeDescription
name requiredstringTemplate name (1–255 characters)
descriptionstringOptional description shown in the template picker
Example
curl -X POST "https://salesbooth.com/api/v1/deals?id=deal_xxxxx&action=save-as-template" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Enterprise Annual Plan", "description": "Standard enterprise deal with annual billing and 10% loyalty discount" }'
GET /api/v1/deals?id={deal_id}&action=audit
Retrieve the immutable audit trail for a deal.
GET /api/v1/deals/{id}/settlements
Retrieve revenue-share settlement records for a closed deal. Returns the final breakdown of proceeds distributed to all participants (seller, buyer, platform, deal participants with revenue-share agreements).
Example
curl "https://salesbooth.com/api/v1/deals/deal_xxxxx/settlements" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "settlements": [ { "participant_id": "part_abc", "role": "seller", "share_percent": 85.00, "amount": 850.00, "currency": "USD", "status": "settled" }, { "participant_id": "part_def", "role": "referrer", "share_percent": 15.00, "amount": 150.00, "currency": "USD", "status": "settled" } ] } }
GET /api/v1/deals/verify?id={deal_id}
Verify deal or contract integrity. Public endpoint — no authentication required. Confirms that a deal or contract has not been tampered with after signing by comparing the current state hash against the signed state hash. Third parties who receive deals can use this to independently verify authenticity.
ParameterTypeDescription
idstringDeal ID to verify (provide either id or contract_id)
contract_idstringContract ID to verify
Example
curl "https://salesbooth.com/api/v1/deals/verify?id=deal_abc123"
Response
{ "error": false, "data": { "verification": { "deal_id": "deal_abc123", "status": "verified", "message": "Deal signature is valid and data is unmodified", "deal_hash": { "stored": "a3f2b1c9...", "current": "a3f2b1c9...", "matches": true }, "signature": { "valid": true, "signature_algorithm": "ed25519", "signed_at": "2026-03-10T14:22:00Z" }, "verification_method": "public_key", "verification_note": "This signature can be independently verified using the public key without trusting Salesbooth infrastructure." } } }

Possible status values: verified (deal matches signed state), tampered (deal was modified after signing), unsigned (no signature exists).

Customers

Manage customer records. Sensitive PII (name, email, phone) is encrypted at rest with searchable blind indexes.

GET /api/v1/customers
List customers with optional filters.
ParameterDescription
idCustomer ID to retrieve a specific customer (e.g. cust_xxxxxxxxxx). When provided, returns a single customer object instead of a list.
statusFilter: active, inactive, archived
searchSearch name, email, or phone
limitMax results, 1–100 (default: 50)
offsetPagination offset (default: 0). Ignored when after/before cursors are provided.
afterCursor for forward pagination. Pass the next_cursor from a previous response.
beforeCursor for backward pagination. Pass the prev_cursor from a previous response.
sortSort field for cursor pagination: created_at (default) or updated_at
fieldsComma-separated list of fields to include in the response (e.g. id,status,name)
includeComma-separated nested resources to include (e.g. deals,contracts,activity_log)
excludeComma-separated nested resources to exclude from the response
formatResponse format shortcut: minimal returns only id, status, and updated_at
GET /api/v1/customers?id={customer_id}
Retrieve a single customer with their deals and activity log.
POST /api/v1/customers
Create a new customer.
Example
curl -X POST https://salesbooth.com/api/v1/customers \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Jane Smith", "email": "jane@example.com", "phone": "+61412345678", "company": "Acme Corp", "status": "active" }'
FieldDescription
name requiredCustomer full name
email requiredEmail address
phonePhone number (E.164 format)
companyCompany or organisation name
cityCity
stateState or region
zipPostal code
countryCountry code (e.g. AU)
addressStreet address
notesInternal notes
statusCustomer status: active (default), inactive, archived
PATCH /api/v1/customers?id={customer_id}
Update an existing customer. Send only the fields you want to change. Requires an If-Match header with the current ETag version for optimistic locking.
FieldTypeDescription
namestringFull name
emailstringEmail address (must be unique per tenant)
phonestringPhone number (normalised to E.164)
addressstringStreet address
companystringCompany name
citystringCity
statestringState or province
zipstringPostal code
countrystringCountry
notesstringInternal notes
statusstringactive, inactive, or archived
Example
curl -X PATCH "https://salesbooth.com/api/v1/customers?id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -H "If-Match: 5" \ -d '{ "phone": "+14155552671", "company": "Acme Corp (updated)", "status": "active" }'
DELETE /api/v1/customers?id={customer_id}
Permanently delete a customer record and all associated data. This action cannot be undone.
Example
curl -X DELETE "https://salesbooth.com/api/v1/customers?id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "If-Match: 1"

Products

Manage your product catalogue. Products can be physical goods or services and are referenced by deal line items.

GET /api/v1/products
List products with optional filters.
ParameterDescription
idProduct ID to retrieve a specific product (e.g. prod_xxxxxxxxxx). When provided, returns a single product object instead of a list.
actionSub-action to perform: options (requires id) — returns the product’s configuration options schema
statusFilter: active, inactive, archived
typeFilter: product, service
categoryFilter by category name
familyFilter by product family ID
requires_bookingFilter to bookable service products: 1 to include only bookable products, 0 to exclude them
searchSearch name, SKU, or description
limitMax results, 1–100 (default: 50)
offsetPagination offset (default: 0). Ignored when after/before cursors are provided.
afterCursor for forward pagination. Pass the next_cursor from a previous response.
beforeCursor for backward pagination. Pass the prev_cursor from a previous response.
sortSort field for cursor pagination: created_at (default) or updated_at
fieldsComma-separated list of fields to include in the response (e.g. id,status,name,price)
includeComma-separated nested resources to include (e.g. deals,activity_log)
excludeComma-separated nested resources to exclude from the response
formatResponse format shortcut: minimal returns only id, status, and updated_at
POST /api/v1/products
Create a new product.
Example
curl -X POST https://salesbooth.com/api/v1/products \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Enterprise License", "price": 999.00, "type": "service", "description": "Annual enterprise license", "sku": "ENT-001" }'
FieldTypeDescription
name requiredstringProduct name
price requirednumberSelling price
descriptionstringProduct description
skustringStock keeping unit
typestringproduct, service, subscription, or bundle
price_typestringonce_off, recurring, percentage, or metered
billing_cyclestringmonthly, quarterly, or annual — required when price_type is recurring
pricing_modelstringfixed, tiered, volume, or usage
costnumberCost price (for margin calculation)
unitstringUnit label (e.g. “per seat”, “per month”)
tax_ratenumberTax rate as decimal (e.g. 0.10 for 10%)
categorystringProduct category
statusstringactive, inactive, or archived (default: active)
stock_quantityintegerAvailable stock quantity
track_inventorybooleanEnable inventory tracking for this product
low_stock_thresholdintegerStock level at which low-stock alerts are triggered
metadataobjectArbitrary key-value metadata
configuration_schemaobjectJSON schema defining configurable options for this product
family_idstringProduct family ID to associate this product with
requires_bookingbooleanWhether this product requires a booking (default: false)
session_durationintegerSession length in minutes (5–480)
buffer_timeintegerBuffer time between sessions in minutes (0–120)
max_advance_daysintegerMaximum days in advance a booking can be made (default: 90)
min_advance_hoursintegerMinimum hours lead time required for a booking (default: 24)
allow_staff_selectionbooleanWhether customers can choose their preferred staff member (default: true)
learn_more_urlstringURL linking to more information about the product
featuresarrayList of product feature strings
PATCH /api/v1/products?id={product_id}
Update an existing product. Send only the fields you want to change. Requires an If-Match header with the current ETag version for optimistic locking.
FieldTypeDescription
namestringProduct name
descriptionstringProduct description
pricenumberUnit price
costnumberCost price (for margin calculation)
skustringStock keeping unit
typestringproduct, service, subscription, or bundle
unitstringUnit label (e.g. “per seat”)
tax_ratenumberTax rate as decimal (e.g. 0.10 for 10%)
categorystringProduct category
statusstringactive, inactive, or archived
stock_quantityintegerAvailable stock quantity
track_inventorybooleanEnable inventory tracking
low_stock_thresholdintegerStock level at which low-stock alerts are triggered
price_typestringonce_off, recurring, percentage, or metered
billing_cyclestringmonthly, quarterly, or annual — required when price_type is recurring
pricing_modelstringfixed, tiered, volume, or usage
metadataobjectArbitrary key-value metadata
configuration_schemaobjectJSON schema defining configurable options for this product
family_idstringProduct family ID to associate this product with
requires_bookingbooleanWhether this product requires a booking
session_durationintegerSession length in minutes (5–480)
buffer_timeintegerBuffer time between sessions in minutes (0–120)
max_advance_daysintegerMaximum days in advance a booking can be made
min_advance_hoursintegerMinimum hours lead time required for a booking
allow_staff_selectionbooleanWhether customers can choose their preferred staff member
learn_more_urlstringURL linking to more information about the product
featuresarrayList of product feature strings
Example
curl -X PATCH "https://salesbooth.com/api/v1/products?id=prod_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -H "If-Match: 2" \ -d '{ "price": 1199.00, "status": "active", "stock_quantity": 50 }'
DELETE /api/v1/products?id={product_id}
Permanently delete a product. Products referenced by existing deal line items cannot be deleted while those deals are active.
Example
curl -X DELETE "https://salesbooth.com/api/v1/products?id=prod_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "If-Match: 1"

Contracts

Create and manage contracts with lifecycle transitions, cryptographic signing, and immutable audit trails.

GET /api/v1/contracts
List contracts with optional filters.
ParameterDescription
idContract ID to retrieve a specific contract. When provided, returns a single contract object instead of a list.
actionAction to perform (requires id): audit, verify_audit, signing_certificate
statusFilter: draft, signed, active, expired, terminated
customer_idFilter by customer
renewal_typeFilter by renewal type: manual, auto, none
expiring_soonFilter contracts expiring within N days (e.g. 30 for contracts expiring in the next 30 days)
limitMax results, 1–100 (default: 50)
offsetPagination offset (default: 0). Ignored when after/before cursors are provided.
afterCursor for forward pagination. Pass the next_cursor from a previous response.
beforeCursor for backward pagination. Pass the prev_cursor from a previous response.
sortSort field for cursor pagination: created_at (default) or updated_at
fieldsComma-separated list of fields to include in the response (e.g. contract_id,status,title,value)
includeComma-separated nested resources to include (e.g. activity_log)
excludeComma-separated nested resources to exclude from the response
formatResponse format shortcut: minimal returns only contract_id, status, and updated_at
POST /api/v1/contracts
Create a new contract. You can create a contract directly, or from an existing deal using deal_id (which auto-populates customer, value, dates, and currency).
Example — create from a deal
curl -X POST https://salesbooth.com/api/v1/contracts \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_xxxxx", "payment_terms": "net30", "renewal_type": "auto" }'
Example — create directly
curl -X POST https://salesbooth.com/api/v1/contracts \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "title": "Annual Support Agreement", "value": 12000.00, "currency": "AUD", "start_date": "2026-04-01", "end_date": "2027-03-31", "payment_terms": "net30", "renewal_type": "auto" }'
FieldDescription
deal_idCreate a contract from an existing deal. Auto-populates customer_id, title, value, currency, start_date, and end_date from the deal. Any of those fields may still be provided to override the deal-derived values. Required unless the five core fields are supplied.
customer_id required*Customer to attach the contract to. Required unless deal_id is provided.
title required*Contract title. Required unless deal_id is provided.
value required*Contract value (numeric, ≥ 0). Required unless deal_id is provided.
start_date required*Contract start date (YYYY-MM-DD). Required unless deal_id is provided.
end_date required*Contract end date (YYYY-MM-DD, must be after start_date). Required unless deal_id is provided.
contract_numberCustom contract reference number (e.g. CTR-2026-001).
descriptionContract description.
currencyISO 4217 currency code (default: USD).
payment_termsPayment terms text (e.g. net30).
renewal_typeRenewal configuration: auto, manual, or none (default: manual).
renewal_termsStructured renewal terms object (JSON). Stores renewal period, notice window, and other renewal-specific configuration.
notesInternal notes (not visible to the customer).

* Required unless deal_id is provided.

PATCH /api/v1/contracts?id={contract_id}
Update fields on an existing contract. Requires an If-Match header with the current ETag for optimistic locking.
FieldDescription
titleContract title
descriptionContract description.
valueContract value (numeric, ≥ 0)
currencyISO 4217 currency code
start_dateContract start date (YYYY-MM-DD)
end_dateContract end date (YYYY-MM-DD, must be after start_date)
renewal_typeRenewal configuration: auto, manual, or none
renewal_termsStructured renewal terms object (JSON). Stores renewal period, notice window, and other renewal-specific configuration.
payment_termsPayment terms text (e.g. net30)
notesInternal notes (not visible to the customer).
statusContract status: draft, signed, active, expired, terminated
customer_idReassign the contract to a different customer.
contract_numberCustom contract reference number (e.g. CTR-2026-001).
Example
curl -X PATCH "https://salesbooth.com/api/v1/contracts?id=42" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -H "If-Match: 1" \ -d '{ "title": "Annual SaaS Agreement (Revised)", "payment_terms": "net30", "end_date": "2027-01-31" }'
DELETE /api/v1/contracts?id={contract_id}
Delete a contract. Active contracts must be terminated first (use the terminate action). Requires an If-Match header with the current ETag.
Example
curl -X DELETE "https://salesbooth.com/api/v1/contracts?id=42" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "If-Match: 2"

Contract Actions

POST /api/v1/contracts?id={contract_id}&action=sign
Sign a draft contract. Creates a cryptographic signature.
POST /api/v1/contracts?id={contract_id}&action=activate
Activate a signed contract.
POST /api/v1/contracts?id={contract_id}&action=terminate
Terminate an active contract.

Payments

Manage the payment lifecycle for deals via Stripe PaymentIntents. Create payment intents, confirm payments, issue refunds, and record manual payments.

GET /api/v1/payments?deal_id={deal_id}
Get payment status for a deal, including Stripe PaymentIntent details and payment history.
ParameterTypeDescription
deal_id requiredstringThe deal identifier
Example
curl https://salesbooth.com/api/v1/payments?deal_id=deal_abc123 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/payments?action=settings
Retrieve payment provider settings and Stripe connection status.
Example
curl https://salesbooth.com/api/v1/payments?action=settings \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/payments?action=create-intent
Create a Stripe PaymentIntent for a deal. Returns a client secret for frontend payment confirmation.
FieldTypeDescription
deal_id requiredstringThe deal to collect payment for
amountnumberAmount in major currency units (defaults to deal total)
currencystringISO 4217 currency code (defaults to deal currency)
Example
curl -X POST https://salesbooth.com/api/v1/payments?action=create-intent \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "amount": 1099.00, "currency": "USD" }'
Response (201)
{ "error": false, "data": { "payment_intent_id": "pi_xxxxx", "client_secret": "pi_xxxxx_secret_xxxxx", "amount": 1099.00, "currency": "usd", "status": "requires_payment_method" } }
POST /api/v1/payments?action=confirm
Confirm a payment intent after the customer has provided a payment method.
FieldTypeDescription
payment_intent_id requiredstringThe Stripe PaymentIntent ID
Example
curl -X POST https://salesbooth.com/api/v1/payments?action=confirm \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "payment_intent_id": "pi_xxxxx" }'
POST /api/v1/payments?action=refund
Issue a full or partial refund on a completed payment.
FieldTypeDescription
payment_intent_id requiredstringThe Stripe PaymentIntent ID to refund
amountnumberPartial refund amount (omit for full refund)
reasonstringRefund reason
Example
curl -X POST https://salesbooth.com/api/v1/payments?action=refund \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "payment_intent_id": "pi_xxxxx", "amount": 200.00, "reason": "Partial refund for returned item" }'
POST /api/v1/payments?action=record-manual
Record a manual (offline) payment for a deal — bank transfer, cheque, or cash.
FieldTypeDescription
deal_id requiredstringThe deal identifier
amount requirednumberPayment amount
currencystringCurrency code
Example
curl -X POST https://salesbooth.com/api/v1/payments?action=record-manual \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "amount": 5000.00 }'

Subscriptions

Create and manage recurring subscriptions built on top of deals. Supports billing cycles, cancellation, pausing, resuming, cycle changes, metered billing, and renewal tracking.

Subscription Lifecycle

┌───────────────────────────────────────────────────────────────────────────┐ │ SUBSCRIPTION STATE MACHINE │ │ │ │ (closed deal) │ │ │ │ │ │ action=create │ │ ▼ │ │ ┌─────────┐ action=pause ┌────────┐ action=cancel ┌───────────┐ │ │ │ active │────────────────▶│ paused │─────────────────▶│ cancelled │ │ │ └─────────┘ └────────┘ └───────────┘ │ │ │ ▲ │ │ │ │ │ action=resume │ action=resume │ │ │ └───────────────────────┘ │ │ │ │ │ │ payment fails at renewal │ │ ▼ │ │ ┌──────────┐ action=retry-payment ┌──────────┐ │ │ │ past_due │───────────────────────▶│ active │ │ │ └──────────┘ (if payment succeeds) └──────────┘ │ │ │ │ │ │ grace period expires │ │ ▼ │ │ ┌───────────┐ │ │ │ suspended │ │ │ └───────────┘ │ └───────────────────────────────────────────────────────────────────────────┘
StatusDescription
activeSubscription is renewing normally. Metered usage is accumulating for the current cycle.
pausedNo renewals will occur. Usage meters stopped. Resume restarts from pause date.
past_dueMost recent renewal payment failed. Subscription continues in grace period; retry payment to return to active.
suspendedGrace period expired without successful payment. Service should be suspended. Requires manual payment recovery.
cancelledSubscription permanently cancelled. end_of_period: true cancels at cycle end; false cancels immediately.
GET /api/v1/subscriptions
List all subscriptions or retrieve a specific one. Pass action=analytics for subscription metrics.
ParameterTypeDescription
idstringRetrieve a specific subscription by deal ID
statusstringFilter: active, paused, cancelled, past_due
actionstringanalytics for subscription metrics; usage (with id) for metered usage records
Example — list active subscriptions
curl "https://salesbooth.com/api/v1/subscriptions?status=active" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Example — get metered usage for a subscription
curl "https://salesbooth.com/api/v1/subscriptions?id=deal_abc123&action=usage_summary" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/subscriptions action=create
Create a recurring subscription from a closed deal.
FieldTypeDescription
deal_id requiredstringThe deal to subscribe
action requiredstringcreate
billing_cyclestringmonthly (default), quarterly, or annual
Example
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "create", "billing_cycle": "monthly" }'
POST /api/v1/subscriptions action=pause
Pause an active subscription. No renewal charges will occur while paused.
Example
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "pause" }'
POST /api/v1/subscriptions action=resume
Resume a paused subscription. The next renewal is recalculated from the resume date.
Example
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "resume" }'
POST /api/v1/subscriptions action=cancel
Cancel a subscription. By default cancels at end of the current billing period.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringcancel
end_of_periodbooleanIf false, cancels immediately (default: true)
Example — cancel at period end
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "cancel", "end_of_period": true }'
POST /api/v1/subscriptions action=renew
Manually trigger a renewal cycle for a subscription. Creates a new renewal deal and processes payment if a payment method is on file. Normally handled automatically by the cron job.
Example
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "renew" }'
POST /api/v1/subscriptions action=retry-payment
Retry a failed renewal payment for a past_due subscription. Optionally extends the grace period.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringretry-payment
grace_daysintegerAdditional days to extend the grace period (optional)
Example
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "retry-payment", "grace_days": 3 }'
POST /api/v1/subscriptions action=change
Upgrade or downgrade a subscription by replacing its line items. Proration is applied at the next renewal cycle.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringchange
line_items requiredarrayNew line items: product_id, quantity, unit_price
Example — upgrade to enterprise plan
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "change", "line_items": [ { "product_id": "prod_enterprise", "quantity": 1, "unit_price": 299.00 } ] }'
GET /api/v1/subscriptions?id={deal_id}&action=usage_summary
Get a summary of metered usage for the current billing cycle across all meters on the subscription.
Example
curl "https://salesbooth.com/api/v1/subscriptions?id=deal_abc123&action=usage_summary" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "cycle_start": "2026-03-01T00:00:00Z", "cycle_end": "2026-04-01T00:00:00Z", "meters": [ { "metric_name": "api_calls", "units_used": 12547, "included_units": 10000, "overage_units": 2547, "unit_price": 0.001, "overage_charge": 2.55, "currency": "USD" } ], "base_amount": 99.00, "metered_amount": 2.55, "estimated_total": 101.55, "currency": "USD" } }
POST /api/v1/subscriptions action=change-cycle
Change the billing cycle for an active subscription. Takes effect at the next renewal.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringchange-cycle
billing_cycle requiredstringmonthly, quarterly, or annual
Example — upgrade to annual
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "change-cycle", "billing_cycle": "annual" }'

Metered Billing

Attach usage meters to subscriptions to bill based on consumption (e.g. API calls, seats, storage). Meters accumulate usage and are billed at renewal.

POST /api/v1/subscriptions action=add-meter
Add a usage meter to a subscription. Define the metric, unit, and price per unit.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringadd-meter
meter_name requiredstringMeter identifier (e.g. api_calls, seats, storage_gb)
unit_labelstringDisplay label (e.g. API Call, Seat)
price_per_unit requirednumberPrice charged per unit of usage
free_unitsintegerIncluded free units per billing period (default: 0)
Example — add API call meter
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "add-meter", "meter_name": "api_calls", "unit_label": "API Call", "price_per_unit": 0.001, "free_units": 10000 }'
POST /api/v1/subscriptions action=remove-meter
Remove a usage meter from a subscription. Accumulated usage for the current billing period is discarded.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringremove-meter
meter_id requiredstringID of the meter to remove
Example — remove API call meter
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "remove-meter", "meter_id": "meter_xyz789" }'
POST /api/v1/subscriptions action=record-usage
Record metered usage for a subscription. Call this from your application whenever a billable event occurs.
FieldTypeDescription
deal_id requiredstringSubscription deal ID
action requiredstringrecord-usage
meter_name requiredstringMeter to record against (must exist on the subscription)
quantity requirednumberUnits consumed in this event
idempotency_keystringOptional idempotency key to prevent duplicate recording
Example — record 150 API calls
curl -X POST https://salesbooth.com/api/v1/subscriptions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "action": "record-usage", "meter_name": "api_calls", "quantity": 150, "idempotency_key": "usage-2026-03-12-batch-7" }'
Webhook events
subscription.meter_added — meter attached to subscription subscription.renewed — renewal processed, metered charges included subscription.past_due — payment failed at renewal

Staff

Manage staff members — service providers who can be assigned to bookable products and scheduled for availability.

Required Scopes

staff:readRequired for listing and retrieving staff members
staff:writeRequired for creating, updating, deactivating staff, and managing schedules
GET /api/v1/staff
List all active staff members, or retrieve a single staff member with their weekly schedule and assigned products.
ParameterTypeDescription
idstringRetrieve a specific staff member with schedule and assigned products
statusstringFilter by status: active, inactive
product_idstringFilter by assigned product
limitintegerMax results to return (default: 50)
offsetintegerPagination offset
Example
curl https://salesbooth.com/api/v1/staff \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/staff
Create a new staff member.
FieldTypeDescription
display_name requiredstringFull display name of the staff member
titlestringJob title or role (e.g. Senior Consultant)
biostringShort biography shown to customers
avatar_urlstringURL of the staff member’s profile photo
user_idstringLinked tenant user account ID
statusstringAccount status: active or inactive
max_daily_sessionsintegerMaximum bookings per day (1–100)
default_session_durationintegerDefault booking duration in minutes (5–480)
buffer_timeintegerBuffer between bookings in minutes (0–240)
timezonestringStaff member’s timezone (e.g. America/New_York)
metadataobjectArbitrary key/value metadata
schedulearrayWeekly availability schedule (up to 7 entries)
product_idsarrayProduct IDs this staff member is qualified to deliver
Example
curl -X POST https://salesbooth.com/api/v1/staff \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "display_name": "Jane Smith", "title": "Senior Consultant", "timezone": "America/New_York" }'
PATCH /api/v1/staff?id={staff_id}
Update a staff member’s profile.
Example
curl -X PATCH "https://salesbooth.com/api/v1/staff?id=staff_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "title": "Lead Consultant" }'
DELETE /api/v1/staff?id={staff_id}
Deactivate a staff member. Deactivated staff are no longer available for new bookings but existing bookings are preserved.
Example
curl -X DELETE "https://salesbooth.com/api/v1/staff?id=staff_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Schedule Management

POST /api/v1/staff?id={staff_id}&action=schedule
Set the weekly availability schedule for a staff member.
FieldTypeDescription
schedule requiredarrayArray of daily schedule objects with day_of_week (0–6), start_time, end_time
Example
curl -X POST "https://salesbooth.com/api/v1/staff?id=staff_xxxxx&action=schedule" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "schedule": [ { "day_of_week": 1, "start_time": "09:00", "end_time": "17:00" }, { "day_of_week": 2, "start_time": "09:00", "end_time": "17:00" } ] }'
POST /api/v1/staff?id={staff_id}&action=assign_product
Assign a staff member to a bookable product so they appear as available during checkout.
FieldTypeDescription
product_id requiredstringThe product to assign the staff member to
Example
curl -X POST "https://salesbooth.com/api/v1/staff?id=staff_xxxxx&action=assign_product" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx" }'

Bookings

Manage service bookings — hold time slots, confirm appointments, track attendance, and handle cancellations.

Required Scopes

bookings:readRequired for listing and retrieving bookings
bookings:writeRequired for creating, updating, and cancelling bookings
GET /api/v1/bookings
List bookings with optional filters, or retrieve a single booking by ID.
ParameterTypeDescription
idstringRetrieve a specific booking
statusstringFilter: held, confirmed, completed, cancelled, no_show
product_idstringFilter by product
staff_idstringFilter by staff member
deal_idstringFilter by associated deal
date_fromstring (date)Start date filter (YYYY-MM-DD)
date_tostring (date)End date filter (YYYY-MM-DD)
actionstringanalytics for booking metrics
periodstringAnalytics period (e.g. 7d, 30d, 90d; default: 30d). Used with action=analytics
limitintegerMax results (default: 50)
offsetintegerPagination offset
Example
curl https://salesbooth.com/api/v1/bookings?status=confirmed \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/bookings
Create or hold a booking slot for a customer. Use status held to temporarily reserve a slot during checkout.
FieldTypeDescription
product_id requiredstringThe bookable product
staff_id requiredstringStaff member to assign the booking to
date requiredstring (date)Appointment date (YYYY-MM-DD)
start_time requiredstring (time)Appointment start time (HH:MM)
durationintegerDuration in minutes (default: 60)
customer_namestringCustomer display name
customer_emailstringCustomer email for confirmation
customer_phonestringCustomer phone number
notesstringBooking notes
Example
curl -X POST https://salesbooth.com/api/v1/bookings \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "staff_id": "staff_xxxxx", "date": "2026-03-20", "start_time": "10:00", "customer_name": "Alice Johnson", "customer_email": "alice@example.com" }'
Response (201)
{ "error": false, "data": { "booking_id": "book_xxxxx", "tenant_id": "tenant_xxxxx", "deal_id": null, "line_item_id": null, "product_id": "prod_xxxxx", "product_name": "60-min Consultation", "staff_id": "staff_xxxxx", "staff_name": "Jane Smith", "customer_id": null, "customer_name": null, "customer_email": null, "customer_phone": null, "booking_date": "2026-03-20", "start_time": "10:00", "end_time": "11:00", "status": "held", "hold_expires_at": "2026-03-20T10:10:00Z", "notes": null, "created_at": "2026-03-20T09:55:00Z", "updated_at": "2026-03-20T09:55:00Z" } }
PATCH /api/v1/bookings?id={booking_id}
Transition a booking through its lifecycle. Send an action field with action-specific parameters.
FieldTypeDescription
action requiredstringconfirm, cancel, complete, no_show, or reschedule

action: confirm

FieldTypeDescription
deal_id requiredstringDeal to associate with this booking confirmation
line_item_idstringSpecific line item within the deal
customer_idstringCustomer to associate with this booking

action: cancel

FieldTypeDescription
reasonstringCancellation reason

action: complete / no_show

No additional fields required.

action: reschedule

FieldTypeDescription
product_id requiredstringBookable product for the new slot
staff_id requiredstringStaff member for the new slot
date requiredstringNew date in YYYY-MM-DD format
start_time requiredstringNew start time in HH:MM format
durationintegerDuration in minutes (5–480, default: 60)
customer_namestringCustomer display name
customer_emailstringCustomer email address
customer_phonestringCustomer phone number
notesstringBooking notes
Example — confirm a booking
curl -X PATCH "https://salesbooth.com/api/v1/bookings?id=book_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "confirm", "deal_id": "deal_xxxxx" }'
Example — reschedule a booking
curl -X PATCH "https://salesbooth.com/api/v1/bookings?id=book_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "reschedule", "product_id": "prod_xxxxx", "staff_id": "staff_xxxxx", "date": "2026-04-10", "start_time": "14:00" }'
DELETE /api/v1/bookings?id={booking_id}
Cancel a booking. Releases the held time slot.
Example
curl -X DELETE "https://salesbooth.com/api/v1/bookings?id=book_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Availability

Check available booking slots for a bookable product. Used by the widget during checkout to present a date picker with real-time slot availability. Authenticated with a publishable key (sb_pub_*) or a secret key with products:read scope.

GET /api/v1/availability
Return available time slots for a product on a specific date, or return a list of available dates for an entire month.
ParameterTypeDescription
product_id requiredstringBookable product to check
datestringDate in YYYY-MM-DD format — returns available time slots for that day
monthstringMonth in YYYY-MM format — returns all dates with availability in the month
staff_idstringOptional — filter slots for a specific staff member
Check a specific date
curl "https://salesbooth.com/api/v1/availability?product_id=prod_xxxxx&date=2026-03-20" \ -H "Authorization: Bearer sb_pub_xxxxx"
Response (date)
{ "error": false, "success": true, "data": { "available_slots": [ { "time": "09:00", "staff_id": "staff_aaa", "staff_name": "Alice" }, { "time": "10:30", "staff_id": "staff_aaa", "staff_name": "Alice" }, { "time": "14:00", "staff_id": "staff_bbb", "staff_name": "Bob" } ] } }
Check a full month
curl "https://salesbooth.com/api/v1/availability?product_id=prod_xxxxx&month=2026-03" \ -H "Authorization: Bearer sb_pub_xxxxx"
Response (month)
{ "error": false, "success": true, "data": { "available_dates": ["2026-03-18", "2026-03-19", "2026-03-20", "2026-03-25"] } }

Negotiations

Agent-to-agent and human-to-agent deal negotiation protocol. Propose terms, counter-propose, accept, or reject — all tracked with full history and optional AI suggestions. Requires agent:negotiate scope for write operations.

Who needs this: Use Negotiations if you want buyers, agents, or both parties to propose and counter-propose deal terms (discount, payment terms, delivery dates) before a deal is finalised. It is also the foundation for AI-automated bargaining between software agents.

When to skip this: For fixed-price deals where no back-and-forth is needed, you can ignore this section entirely. Create the deal, add line items, and transition directly to in_progress.

Prerequisite: An API key with agent:negotiate scope.

Negotiation Lifecycle

┌─────────────────────────────────────────────────────────────────────┐ │ NEGOTIATION STATE MACHINE │ │ │ │ ┌──────────┐ │ │ propose │ │ counter │ │ ┌───────────▶│ proposed │─────────────┐ │ │ │ │ │ │ │ │ │ └──────────┘ ▼ │ │ (no prior │ │ │ ┌──────────────┐ │ │ history) │ accept reject │ counter_ │ │ │ │ │ │ │ proposed │ │ │ │ ▼ ▼ └──────────────┘ │ │ │ ┌──────────────┐ │ │ │ │ │ │ accepted / │ accept reject │ │ │ │ rejected │ │ │ │ │ │ └──────────────┘ ▼ ▼ │ │ │ ┌──────────────┐ │ │ │ │ accepted / │ │ │ │ │ rejected │ │ │ │ └──────────────┘ │ │ │ │ │ Note: rounds can continue indefinitely until accepted, │ │ rejected, or the proposal expires (expires_at reached) │ └─────────────────────────────────────────────────────────────────────┘
StatusDescriptionNext valid actions
proposedInitial proposal submitted; awaiting response from other partycounter, accept, reject
counter_proposedCounter-proposal made; awaiting response from original proposercounter, accept, reject
acceptedTerms agreed — deal terms updated to reflect final negotiated values(terminal)
rejectedProposal rejected; no further rounds(terminal)
expiredProposal TTL elapsed without response(terminal)
GET /api/v1/deal-negotiations?deal_id={deal_id}
Get the full negotiation history for a deal, including all proposals, counter-proposals, and outcomes.
ParameterTypeDescription
deal_id requiredstringThe deal identifier
Example
curl "https://salesbooth.com/api/v1/deal-negotiations?deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "status": "counter_proposed", "total_rounds": 2, "rounds": [ { "round": 1, "type": "proposal", "proposed_by": "agent", "proposed_terms": { "discount_percent": 15, "quantity": 10 }, "message": "Volume order — requesting 15% discount", "expires_at": "2026-03-16T10:00:00Z", "created_at": "2026-03-09T10:00:00Z" }, { "round": 2, "type": "counter", "proposed_by": "merchant", "proposed_terms": { "discount_percent": 10, "quantity": 10 }, "message": "We can offer 10% for this volume", "expires_at": "2026-03-18T10:00:00Z", "created_at": "2026-03-09T10:05:00Z" } ] } }
GET /api/v1/deal-negotiations?deal_id={deal_id}&action=intelligence
Get pricing intelligence for a deal in the context of a negotiation. Returns suggested counter-offer ranges, historical comparables, and confidence score.
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "suggested_counter": { "discount_percent": 8 }, "acceptable_range": { "discount_min": 5, "discount_max": 12 }, "confidence": "high", "comparable_deals": 34, "avg_accepted_discount": 7.8 } }
POST /api/v1/deal-negotiations?action={action}&deal_id={deal_id}
Submit a negotiation action: propose, counter, accept, or reject.
FieldTypeDescription
action requiredstringpropose, counter, accept, reject
deal_id requiredstringThe deal identifier
proposed_termsobjectTerms to propose (required for propose and counter). Free-form key/value pairs: e.g. discount_percent, quantity, payment_terms
messagestringOptional message to accompany the proposal
expires_atstringISO 8601 expiry for this round (defaults to 7 days)
reasonstringRejection reason (optional, used with reject)
Example — propose terms
curl -X POST "https://salesbooth.com/api/v1/deal-negotiations?action=propose&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "proposed_terms": { "discount_percent": 15, "payment_terms": "net_30" }, "message": "Volume order — requesting 15% discount with net-30 terms", "expires_at": "2026-03-19T00:00:00Z" }'
Example — counter-propose
curl -X POST "https://salesbooth.com/api/v1/deal-negotiations?action=counter&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "proposed_terms": { "discount_percent": 10, "payment_terms": "net_15" }, "message": "We can offer 10% with net-15 terms" }'
Example — accept
curl -X POST "https://salesbooth.com/api/v1/deal-negotiations?action=accept&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{}'
Example — reject
curl -X POST "https://salesbooth.com/api/v1/deal-negotiations?action=reject&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "reason": "Terms do not meet minimum margin requirements" }'
POST /api/v1/deal-negotiations?action=suggest&deal_id={deal_id}
Get AI-generated counter-offer suggestions for the current negotiation round. Returns suggested terms, confidence scores, and data quality metrics. Fires a negotiation.suggestion_generated webhook.
FieldTypeDescription
deal_id requiredstringThe deal identifier
current_termsobjectThe latest proposed terms (if omitted, uses the most recent round from history)
Example
curl -X POST "https://salesbooth.com/api/v1/deal-negotiations?action=suggest&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "current_terms": { "discount_percent": 15, "payment_terms": "net_30" } }'
Response
{ "error": false, "data": { "suggestions": [ { "strategy": "balanced", "proposed_terms": { "discount_percent": 10, "payment_terms": "net_15" }, "confidence": 0.82, "rationale": "10% discount with net-15 closes 69% of similar deals; net-30 adds payment risk" }, { "strategy": "aggressive", "proposed_terms": { "discount_percent": 7, "payment_terms": "net_7" }, "confidence": 0.61, "rationale": "Maximum margin protection; 41% acceptance rate at this price point" } ], "data_quality": { "comparable_deals": 52, "confidence_level": "high" } } }

Deal Templates

Reusable deal templates for programmatic offer generation. Create templates with pre-defined line items and terms, then instantiate them into real deals.

GET /api/v1/deal-templates
List deal templates with optional filters.
ParameterTypeDescription
idstringRetrieve a specific template
statusstringFilter: active, inactive
categorystringFilter by category
searchstringSearch by name or description
limitintegerMax results, 1–100 (default: 50)
offsetintegerPagination offset
Example
curl https://salesbooth.com/api/v1/deal-templates \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/deal-templates
Create a new deal template.
FieldTypeDescription
name requiredstringTemplate name
descriptionstringTemplate description
categorystringTemplate category
default_termsobjectDefault deal terms (currency, tax_rate, etc.)
line_itemsarrayPre-defined line items with product_id, quantity, unit_price
metadataobjectCustom metadata
Example
curl -X POST https://salesbooth.com/api/v1/deal-templates \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Enterprise Starter Pack", "category": "enterprise", "default_terms": { "currency": "USD", "tax_rate": 0.10 }, "line_items": [ { "product_id": "prod_xxxxx", "quantity": 1, "unit_price": 999.00 } ] }'
POST /api/v1/deal-templates?id={template_id}&action=create-deal
Instantiate a template into a real deal. Creates a deal with the template’s pre-defined line items and terms.
FieldTypeDescription
customer_idstringCustomer for the new deal
overridesobjectOverride default terms (currency, tax_rate, etc.)
Example
curl -X POST "https://salesbooth.com/api/v1/deal-templates?id=dtpl_xxxxx&action=create-deal" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx" }'
PATCH /api/v1/deal-templates?id={template_id}
Update a deal template. Send only the fields you want to change.
Example
curl -X PATCH "https://salesbooth.com/api/v1/deal-templates?id=dtpl_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Template Name" }'
DELETE /api/v1/deal-templates?id={template_id}
Delete a deal template.
Example
curl -X DELETE "https://salesbooth.com/api/v1/deal-templates?id=dtpl_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Delegations

Grant AI agents scoped, time-limited access with spending caps and delegation chains. Use delegations to give sub-agents constrained permissions without sharing your primary API key.

Who needs this: Use Delegations if you are building an AI agent that needs to spawn sub-agents or hand off tasks to other services while strictly limiting what those sub-agents are allowed to spend or do. Common use cases include procurement bots, approval-gate workflows, and multi-tenant SaaS where resellers act on behalf of customers.

When to skip this: If all API calls originate from your own server using a single API key, you don’t need delegations. They are only relevant when you are distributing authority across multiple keys, agents, or third parties.

Prerequisite: An API key with agent:execute scope and trust level ≥ 2 (Established).

Chain depth & spending caps: Delegations form a chain — Agent A can delegate a subset of its permissions to Agent B, which can sub-delegate to Agent C. The platform enforces:

  • Downward only: A child delegation can never grant more permissions than the parent delegation it was created from.
  • Spending caps cascade: Each transaction is checked against the per-transaction, daily, and monthly limits of every delegation in the chain. The most restrictive limit always wins.
  • Expiry propagates: If any delegation in the chain expires or is revoked, all sub-delegations become invalid immediately.

Include delegation: Pass the X-Delegation-ID header on API requests or MCP calls to operate within a delegation’s spending limits and scope constraints.

GET /api/v1/delegations
List delegations you have created, or retrieve a specific delegation by ID. Use action=verify to check validity and remaining budget.
ParameterTypeDescription
idstringRetrieve a specific delegation
actionstringverify — check validity and budget; summary — dashboard summary; pending — incoming proposals (agent key only)
limitintegerMax results (default: 50)
offsetintegerPagination offset
Example — verify delegation status and budget
curl "https://salesbooth.com/api/v1/delegations?id=del_xxxxx&action=verify" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "delegation_id": "del_xxxxx", "status": "active", "valid": true, "allowed_actions": ["deals:read", "deals:write", "agent:negotiate"], "spending": { "max_transaction_amount": 5000.00, "max_daily_amount": 25000.00, "max_monthly_amount": null, "spent_today": 3750.00, "remaining_today": 21250.00, "spent_this_month": 48200.00 }, "expires_at": "2026-06-01T00:00:00Z", "grantee_key_id": "key_agent_xxxxx" } }
POST /api/v1/delegations
Create a new delegation granting an agent API key a subset of your permissions with optional spending limits.
FieldTypeDescription
grantee_agent_key_id requiredstringThe agent API key ID to delegate to
allowed_actions requiredarrayPermitted actions (scope-based): deals:read, deals:write, agent:negotiate, deals:sign, customers:read, customers:write
max_transaction_amountnumberPer-transaction spending cap (null = no limit)
max_daily_amountnumberDaily spending cap (resets at midnight UTC)
max_monthly_amountnumberMonthly spending cap (resets on the 1st)
expires_atstringDelegation expiry (ISO 8601, must be in the future)
descriptionstringHuman-readable description of the delegation purpose (max 500 chars)
approval_thresholdnumberTransaction amount above which approval is required
approval_stepsobjectMulti-step approval workflow configuration
approval_timeoutintegerHours before pending approval auto-expires (0–720)
auto_approve_policyobjectConditions under which transactions are auto-approved
alert_threshold_pctintegerSpending alert when daily/monthly usage reaches this percentage (1–100)
signing_authority_acknowledgedbooleanRequired when allowed_actions includes sign authority. Confirms principal authorises agent to execute binding agreements.
Example
curl -X POST https://salesbooth.com/api/v1/delegations \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "grantee_agent_key_id": "key_agent_xxxxx", "allowed_actions": ["deals:read", "deals:write", "agent:negotiate"], "max_transaction_amount": 5000.00, "max_daily_amount": 25000.00, "expires_at": "2026-06-01T00:00:00Z" }'
Response (201)
{ "error": false, "data": { "delegation_id": "del_xxxxx", "tenant_id": "tenant_abc123", "grantor_type": "user", "grantor_id": "42", "grantee_agent_key_id": "key_agent_xxxxx", "description": null, "max_transaction_amount": "5000.00", "max_daily_amount": "25000.00", "max_monthly_amount": null, "spent_today": "0.00", "spent_this_month": "0.00", "reserved_today": "0.00", "reserved_this_month": "0.00", "available_today": "25000.00", "available_this_month": null, "allowed_actions": ["deals:read", "deals:write", "agent:negotiate"], "delegation_chain": [], "expires_at": "2026-06-01 00:00:00", "revoked_at": null, "created_at": "2026-03-12 10:00:00", "updated_at": "2026-03-12 10:00:00", "approval_threshold": null, "approval_steps": null, "approval_timeout": null, "auto_approve_policy": null, "alert_threshold_pct": null } }
PUT /api/v1/delegations?id={delegation_id}
Update a delegation’s allowed actions, spending limits, or expiry. You can only reduce permissions, not expand beyond the original grant.
Example
curl -X PUT "https://salesbooth.com/api/v1/delegations?id=del_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "max_transaction_amount": 2500.00, "expires_at": "2026-05-01T00:00:00Z" }'
DELETE /api/v1/delegations?id={delegation_id}
Revoke a delegation immediately. All child delegations in the chain are also invalidated.
Example
curl -X DELETE "https://salesbooth.com/api/v1/delegations?id=del_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Agent Proposal Flow

Agents can propose delegations to each other without requiring direct API access. The target agent receives the proposal and accepts, rejects, or counters it. The negotiation cycle repeats until both parties agree or the proposal expires.

GET /api/v1/delegations/proposals
List pending delegation proposals targeting this agent. Requires agent API key auth and delegations:read scope.
ParameterTypeDescription
limitintegerMax results (default: 50, max: 100)
offsetintegerPagination offset (default: 0)
Example
curl "https://salesbooth.com/api/v1/delegations/proposals" \ -H "Authorization: Bearer sb_agent_key_do_not_use"
Response
{ "error": false, "data": { "proposals": [ { "id": "dprop_xxxxx", "status": "pending", "proposer_api_key_id": "key_agent_aaaaa", "target_api_key_id": "key_agent_bbbbb", "proposed_actions": ["discover", "negotiate"], "proposed_spending_limits": { "max_transaction_amount": 1000.00 }, "proposed_duration_hours": 168, "message": "Requesting delegation to negotiate deals on your behalf", "round": 1, "expires_at": "2026-03-23T10:00:00Z", "created_at": "2026-03-16T10:00:00Z" } ], "pagination": { "total": 1, "limit": 50, "offset": 0 } } }
POST /api/v1/delegations/proposals
Propose a delegation to a target agent. Requires trust level 2+ and the delegate action in the proposer’s own delegation scope.
FieldTypeDescription
target_api_key_id requiredstringAPI key ID of the target agent
proposed_actions requiredarrayActions being proposed (e.g. discover, negotiate)
max_transaction_amountnumberProposed per-transaction spending cap
max_daily_amountnumberProposed daily spending cap
max_monthly_amountnumberProposed monthly spending cap
proposed_duration_hoursintegerDelegation duration from acceptance (default: 168 = 1 week)
messagestringOptional message to the target agent explaining the request
Example
curl -X POST https://salesbooth.com/api/v1/delegations/proposals \ -H "Authorization: Bearer sb_agent_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "target_api_key_id": "key_agent_bbbbb", "proposed_actions": ["discover", "negotiate"], "max_transaction_amount": 1000.00, "proposed_duration_hours": 168, "message": "Requesting delegation to negotiate deals on your behalf" }'
Response (201)
{ "error": false, "data": { "id": "dprop_xxxxx", "status": "pending", "proposer_api_key_id": "key_agent_aaaaa", "target_api_key_id": "key_agent_bbbbb", "proposed_actions": ["discover", "negotiate"], "proposed_spending_limits": { "max_transaction_amount": 1000.00 }, "proposed_duration_hours": 168, "message": "Requesting delegation to negotiate deals on your behalf", "round": 1, "expires_at": "2026-03-23T10:00:00Z", "created_at": "2026-03-16T10:00:00Z" } }
POST /api/v1/delegations/proposals/{id}/accept
Accept an incoming delegation proposal. Creates an active delegation from the agreed terms. Requires agent API key auth.
Example
curl -X POST "https://salesbooth.com/api/v1/delegations/proposals/dprop_xxxxx/accept" \ -H "Authorization: Bearer sb_agent_key_do_not_use"
Response
{ "error": false, "data": { "proposal": { "id": "dprop_xxxxx", "status": "accepted", "resolved_at": "2026-03-16T10:05:00Z" }, "delegation": { "id": "del_yyyyy", "status": "active", "allowed_actions": ["discover", "negotiate"] } } }
POST /api/v1/delegations/proposals/{id}/reject
Reject an incoming delegation proposal. The proposal is marked as rejected and no delegation is created.
FieldTypeDescription
reasonstringOptional rejection reason sent back to the proposer
Example
curl -X POST "https://salesbooth.com/api/v1/delegations/proposals/dprop_xxxxx/reject" \ -H "Authorization: Bearer sb_agent_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "reason": "Spending limit too high for current context" }'
POST /api/v1/delegations/proposals/{id}/counter
Counter-propose modified delegation terms. The target agent proposes a subset of the original terms. Creates a new proposal round; the original proposer can then accept, reject, or counter again.
FieldTypeDescription
proposed_actions requiredarrayCounter-proposed actions (must be subset of original)
max_transaction_amountnumberCounter-proposed per-transaction cap
max_daily_amountnumberCounter-proposed daily cap
max_monthly_amountnumberCounter-proposed monthly cap
proposed_duration_hoursintegerCounter-proposed duration in hours
messagestringOptional message explaining the counter-proposal
Example
curl -X POST "https://salesbooth.com/api/v1/delegations/proposals/dprop_xxxxx/counter" \ -H "Authorization: Bearer sb_agent_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "proposed_actions": ["discover"], "max_transaction_amount": 500.00, "proposed_duration_hours": 72, "message": "Accepting discover only with lower spending limit" }'
Response (201)
{ "error": false, "data": { "id": "dprop_zzzzz", "status": "pending", "previous_proposal_id": "dprop_xxxxx", "proposed_actions": ["discover"], "proposed_spending_limits": { "max_transaction_amount": 500.00 }, "proposed_duration_hours": 72, "round": 2, "expires_at": "2026-03-23T10:05:00Z", "created_at": "2026-03-16T10:05:00Z" } }

Using a Delegation

Pass the X-Delegation-ID header to operate within a delegation’s constraints. All spending is tracked against the delegation’s caps and propagated up the chain.

curl -X POST https://salesbooth.com/api/v1/deals \ -H "Authorization: Bearer sb_agent_key_do_not_use" \ -H "X-Delegation-ID: del_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "currency": "USD" }' # If the deal value would exceed max_transaction_amount, returns 429 spending_limit_exceeded

Product Families

Top-level groupings for organizing related products. Families define the structure for the product configurator.

GET /api/v1/product-families
List product families or retrieve a specific family.
ParameterTypeDescription
idstringRetrieve a specific family
statusstringFilter: active, archived
searchstringSearch by name
Example
curl https://salesbooth.com/api/v1/product-families \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/product-families
Create a new product family.
FieldTypeDescription
name requiredstringFamily name
descriptionstringFamily description
slugstringURL-friendly slug
sort_orderintegerDisplay order
image_urlstringFamily image URL
statusstringactive or archived
Example
curl -X POST https://salesbooth.com/api/v1/product-families \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Cloud Infrastructure", "description": "Cloud hosting and compute products" }'
PATCH /api/v1/product-families?id={family_id}
Update a product family.
Example
curl -X PATCH "https://salesbooth.com/api/v1/product-families?id=pf_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Family Name" }'
DELETE /api/v1/product-families?id={family_id}
Archive a product family.
Example
curl -X DELETE "https://salesbooth.com/api/v1/product-families?id=pf_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Option Groups

Reusable configuration building blocks. Option groups define selectable options (e.g. colours, sizes, add-ons) that can be linked to products.

GET /api/v1/option-groups
List option groups or retrieve a specific group with its options.
ParameterTypeDescription
idstringRetrieve a specific group
statusstringFilter: active, archived
searchstringSearch by name
include_optionsbooleanInclude options in response
Example
curl https://salesbooth.com/api/v1/option-groups?include_options=true \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/option-groups
Create a new option group.
FieldTypeDescription
name requiredstringGroup name (e.g. “Colour”, “Storage”)
descriptionstringGroup description
selection_typestringsingle or multiple
is_requiredbooleanWhether selection is required
min_selectionsintegerMinimum options the customer must select (0–100)
max_selectionsintegerMaximum options the customer can select (0–100)
display_stylestringcards, dropdown, pills, swatches, checkboxes
sort_orderintegerDisplay order
Example
curl -X POST https://salesbooth.com/api/v1/option-groups \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Storage Capacity", "selection_type": "single", "is_required": true, "display_style": "cards" }'

Options within Groups

POST /api/v1/option-groups?id={group_id}&action=options
Add an option to a group.
Example
curl -X POST "https://salesbooth.com/api/v1/option-groups?id=og_xxxxx&action=options" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "256 GB", "price_modifier": 100.00, "sort_order": 1 }'
PATCH /api/v1/option-groups?id={group_id}
Update an option group or a specific option within it.
Example
curl -X PATCH "https://salesbooth.com/api/v1/option-groups?id=og_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Group Name" }'
DELETE /api/v1/option-groups?id={group_id}
Archive an option group or a specific option.
Example
curl -X DELETE "https://salesbooth.com/api/v1/option-groups?id=og_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Bundle Rules

Define discount conditions when multiple options are selected together. Bundle rules automatically apply pricing incentives.

GET /api/v1/bundle-rules
List bundle pricing rules, optionally filtered by product.
ParameterTypeDescription
idstringRetrieve a specific rule
product_idstringFilter by product
is_activebooleanFilter by active status
Example
curl https://salesbooth.com/api/v1/bundle-rules?product_id=prod_xxxxx \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/bundle-rules
Create a bundle pricing rule.
FieldTypeDescription
name requiredstringRule name
product_id requiredstringProduct this rule applies to
option_ids requiredarrayOption IDs that trigger the bundle
discount_type requiredstringpercentage or fixed
discount_value requirednumberDiscount amount (percent or fixed)
min_optionsintegerMinimum options needed (default: all)
Example
curl -X POST https://salesbooth.com/api/v1/bundle-rules \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Full Suite Bundle", "product_id": "prod_xxxxx", "option_ids": ["opt_aaa", "opt_bbb", "opt_ccc"], "discount_type": "percentage", "discount_value": 15, "min_options": 3 }'
PATCH /api/v1/bundle-rules?id={rule_id}
Update a bundle pricing rule.
Example
curl -X PATCH "https://salesbooth.com/api/v1/bundle-rules?id=br_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "discount_value": 20 }'
DELETE /api/v1/bundle-rules?id={rule_id}
Delete a bundle pricing rule.
Example
curl -X DELETE "https://salesbooth.com/api/v1/bundle-rules?id=br_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Compatibility Rules

Define requires, excludes, and includes_price relationships between options. Compatibility rules prevent invalid configurations.

GET /api/v1/compatibility-rules
List compatibility rules, optionally filtered by product or rule type.
ParameterTypeDescription
idstringRetrieve a specific rule
product_idstringFilter by product
rule_typestringFilter: requires, excludes, includes_price
source_option_idstringFilter by source option
Example
curl https://salesbooth.com/api/v1/compatibility-rules?product_id=prod_xxxxx \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/compatibility-rules
Create a compatibility rule between two options.
FieldTypeDescription
source_option_id requiredstringThe triggering option
target_option_id requiredstringThe affected option
rule_type requiredstringrequires, excludes, or includes_price
product_id requiredstringProduct this rule applies to
messagestringUser-facing message when rule triggers
Example
curl -X POST https://salesbooth.com/api/v1/compatibility-rules \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "source_option_id": "opt_ssd", "target_option_id": "opt_raid", "rule_type": "requires", "product_id": "prod_xxxxx", "message": "RAID controller requires SSD storage" }'
PATCH /api/v1/compatibility-rules?id={rule_id}
Update a compatibility rule.
Example
curl -X PATCH "https://salesbooth.com/api/v1/compatibility-rules?id=cr_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "message": "Updated compatibility message" }'
DELETE /api/v1/compatibility-rules?id={rule_id}
Delete a compatibility rule.
Example
curl -X DELETE "https://salesbooth.com/api/v1/compatibility-rules?id=cr_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Product Option Groups

Link option groups to specific products and manage per-product option availability overrides. Controls which option groups appear for a product and which individual options are available or hidden.

GET /api/v1/product-option-groups?product_id={product_id}
Get linked option groups and per-product option availability for a product.
ParameterTypeDescription
product_id requiredstringThe product identifier
actionstringavailability to list per-option availability overrides
Example
curl "https://salesbooth.com/api/v1/product-option-groups?product_id=prod_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/product-option-groups
Link an option group to a product, or set per-option availability overrides.
FieldTypeDescription
product_id requiredstringThe product identifier
group_idstringOption group to link (required when not setting availability)
sort_order_overrideintegerOverride display order for this product
is_required_overridebooleanOverride whether the group is required
actionstringavailability to set per-option availability (requires option_id and is_available)
Example — Link option group
curl -X POST https://salesbooth.com/api/v1/product-option-groups \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "group_id": "grp_xxxxx", "sort_order_override": 1, "is_required_override": true }'
PATCH /api/v1/product-option-groups
Update link overrides or option availability for a product–option group association.
Example
curl -X PATCH https://salesbooth.com/api/v1/product-option-groups \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "group_id": "grp_xxxxx", "sort_order_override": 2 }'
DELETE /api/v1/product-option-groups
Unlink an option group from a product, or remove a per-option availability override.
FieldTypeDescription
product_id requiredstringThe product identifier
group_idstringOption group to unlink
Example
curl -X DELETE https://salesbooth.com/api/v1/product-option-groups \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "group_id": "grp_xxxxx" }'

Product Rules

Retrieve an aggregate view of all configuration rules (compatibility and bundle rules) for a product, and validate option selections against those rules.

GET /api/v1/product-rules?product_id={product_id}
Get all active compatibility and bundle rules for a product in a single request.
ParameterTypeDescription
product_id requiredstringThe product identifier
Example
curl "https://salesbooth.com/api/v1/product-rules?product_id=prod_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/product-rules
Validate a configuration — a set of selected option IDs — against all rules for a product. Returns any violations with human-readable messages.
FieldTypeDescription
product_id requiredstringThe product identifier
selected_options requiredarrayArray of selected option IDs to validate
Example
curl -X POST https://salesbooth.com/api/v1/product-rules \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "selected_options": ["opt_ssd_512", "opt_ram_32gb"] }'
Response
{ "error": false, "data": { "valid": true, "violations": [], "price_adjustments": [ { "reason": "Bundle discount: SSD + 32GB RAM", "amount": -50.00 } ] } }

Configuration (CPQ)

Unified CPQ (Configure, Price, Quote) API for AI agents and widget interactions. Get product schemas with rules, validate configurations, and calculate pricing.

GET /api/v1/configuration?product_id={product_id}
Get the full configuration schema for a product, including option groups, compatibility rules, and bundle rules.
ParameterTypeDescription
product_id requiredstringProduct identifier
Example
curl https://salesbooth.com/api/v1/configuration?product_id=prod_xxxxx \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/configuration?action=families
List all product families for the configurator.
Example
curl https://salesbooth.com/api/v1/configuration?action=families \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/configuration?product_id={product_id}&action=validate
Validate a set of selected options against the product’s configuration rules.
FieldTypeDescription
option_ids requiredarrayArray of selected option IDs
Example
curl -X POST "https://salesbooth.com/api/v1/configuration?product_id=prod_xxxxx&action=validate" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "option_ids": ["opt_aaa", "opt_bbb"] }'
Response
{ "error": false, "data": { "valid": true, "violations": [], "bundles_applied": ["Full Suite Bundle"] } }
POST /api/v1/configuration?product_id={product_id}&action=price
Calculate pricing for a configuration, including bundle discounts and option price modifiers.
FieldTypeDescription
option_ids requiredarrayArray of selected option IDs
Example
curl -X POST "https://salesbooth.com/api/v1/configuration?product_id=prod_xxxxx&action=price" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "option_ids": ["opt_aaa", "opt_bbb"] }'
Response
{ "error": false, "data": { "base_price": 999.00, "option_total": 200.00, "bundle_discount": -59.85, "subtotal": 1139.15, "breakdown": [ { "option_id": "opt_aaa", "name": "256 GB SSD", "price": 100.00 }, { "option_id": "opt_bbb", "name": "RAID Controller", "price": 100.00 } ] } }

Webhooks

Subscribe to real-time events. Salesbooth will send an HTTP POST to your endpoint when events occur.

GET /api/v1/webhooks
List all registered webhooks.
POST /api/v1/webhooks
Register a new webhook.
FieldTypeDescription
url requiredstringHTTPS endpoint URL to receive webhook events
events requiredarrayEvent types to subscribe to (e.g. deal.created)
descriptionstringOptional human-readable description (max 255 chars)
Example
curl -X POST https://salesbooth.com/api/v1/webhooks \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "url": "https://myapp.com/webhooks/salesbooth", "events": ["deal.created"] }'
New webhooks start as active by default. To pause a webhook, use PATCH with "status": "paused".
PATCH /api/v1/webhooks?id={webhook_id}
Update an existing webhook’s URL, subscribed events, status, or description.
FieldDescription
urlNew endpoint URL
eventsArray of event type strings to subscribe to
statusactive or paused
descriptionHuman-readable description
Example
curl -X PATCH "https://salesbooth.com/api/v1/webhooks?id=wh_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "status": "paused", "events": ["deal.created", "deal.closed", "payment.received"] }'
DELETE /api/v1/webhooks?id={webhook_id}
Permanently remove a webhook registration. Future events will no longer be delivered to this endpoint.
Example
curl -X DELETE "https://salesbooth.com/api/v1/webhooks?id=wh_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/webhooks/rotate_secret?id={webhook_id}
Rotate the signing secret for a webhook.
GET /api/v1/webhooks?id={webhook_id}&action=deliveries
Get delivery history for a webhook, including status and response codes.
GET /api/v1/webhooks/deliveries
List delivery attempts for a specific webhook with filtering and pagination.
ParameterDescription
id requiredWebhook ID to retrieve deliveries for
statusFilter by delivery status: pending, success, or failed
event_typeFilter by event type (e.g. deal.created)
limitNumber of results to return (default 50, max 100)
offsetPagination offset (default 0)
Example
curl "https://salesbooth.com/api/v1/webhooks/deliveries?id=wh_xxxxx&status=failed&limit=25" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "deliveries": [ { "delivery_id": "dlv_abc123", "webhook_id": "wh_xxxxx", "event_type": "deal.created", "status": "failed", "attempts": 3, "response_code": 500, "error_message": "Connection timeout", "delivered_at": null, "created_at": "2026-03-09T10:30:00Z" } ], "pagination": { "total": 42, "limit": 25, "offset": 0, "count": 1 } } }
GET /api/v1/webhooks/events
List webhook event history with cursor-based pagination. Use since_sequence or since_timestamp to resume from a known position.
ParameterDescription
since_sequenceReturn events after this sequence number (cursor-based pagination)
since_timestampReturn events after this ISO 8601 timestamp
event_typeFilter by event type (e.g. deal.created)
statusFilter by delivery status: pending, delivered, partially_delivered, or failed
limitNumber of results to return (1–100, default 50)
Example
curl "https://salesbooth.com/api/v1/webhooks/events?since_sequence=1500&limit=50" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "events": [ { "id": "evt_abc123", "sequence": 1501, "event_type": "deal.created", "status": "delivered", "created_at": "2026-03-09T10:30:00Z" } ], "cursor": { "last_sequence": 1550, "has_more": true } } }
GET /api/v1/webhooks/dead_letter
List deliveries that exhausted all retry attempts (maximum 3) and are now in the dead-letter queue. Use /webhooks/replay or /webhooks/retry to re-deliver them.
ParameterDescription
event_typeFilter by event type
webhook_idFilter by webhook ID
limitNumber of results to return (default 50)
offsetPagination offset (default 0)
Example
curl "https://salesbooth.com/api/v1/webhooks/dead_letter?webhook_id=wh_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "dead_letters": [ { "delivery_id": "dlv_abc123", "webhook_id": "wh_xxxxx", "event_id": "evt_abc123", "event_type": "deal.created", "attempts": 3, "last_error": "Connection refused", "last_attempted_at": "2026-03-09T12:00:00Z", "created_at": "2026-03-09T10:30:00Z" } ], "pagination": { "total": 7, "limit": 50, "offset": 0, "count": 1 } } }
POST /api/v1/webhooks/test
Send a test event to a webhook endpoint to verify connectivity and your handler logic.
FieldTypeDescription
id requiredqueryWebhook ID to send the test event to
event_typebodyEvent type to simulate (default: deal.created)
Example
curl -X POST "https://salesbooth.com/api/v1/webhooks/test?id=wh_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "event_type": "deal.created" }'
Response
{ "error": false, "success": true, "data": { "success": true, "response_code": 200, "response_body": "OK", "latency_ms": 45, "error_message": null, "event_type": "deal.created" } }
POST /api/v1/webhooks/replay
Re-deliver events from a given sequence number or timestamp to a webhook. Rate limited to 100 events per request. Replayed deliveries include an X-Salesbooth-Replayed: true header.
FieldDescription
webhook_id requiredTarget webhook to replay events to
since_sequenceReplay events after this sequence number
since_timestampReplay events after this ISO 8601 timestamp
event_typeOnly replay a specific event type
Example
curl -X POST https://salesbooth.com/api/v1/webhooks/replay \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "webhook_id": "wh_xxxxx", "since_timestamp": "2026-03-09T00:00:00Z", "event_type": "deal.created" }'
Response
{ "error": false, "success": true, "data": { "replayed": 42, "webhook_id": "wh_xxxxx", "has_more": false, "events": [ { "event_id": "evt_abc123", "event_sequence": 1501, "event_type": "deal.created", "delivery_id": "dlv_new456" } ] } }
POST /api/v1/webhooks/retry
Manually retry a specific failed delivery. Resets the delivery to pending and attempts immediate re-delivery.
FieldDescription
delivery_id requiredID of the failed delivery to retry
Example
curl -X POST https://salesbooth.com/api/v1/webhooks/retry \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "delivery_id": "dlv_abc123" }'
Response
{ "error": false, "success": true, "data": { "delivery": { "delivery_id": "dlv_abc123", "status": "success", "attempts": 4, "response_code": 200, "error_message": null, "retried_at": "2026-03-09T18:00:00Z" } } }
POST /api/v1/webhooks/cleanup
Delete delivered webhook events older than the retention period. Safe to call from a cron job.
FieldDescription
retention_daysDays of events to retain (default 30)
batch_sizeMaximum records to delete per run (default 10000)
Example
curl -X POST https://salesbooth.com/api/v1/webhooks/cleanup \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "retention_days": 30, "batch_size": 10000 }'
Response
{ "error": false, "success": true, "data": { "cutoff_date": "2026-02-09T00:00:00Z", "retention_days": 30, "events_deleted": 4821, "deliveries_deleted": 9203 } }

Available Events

Deal Events
deal.createdA new deal was created
deal.updatedA deal's fields were updated
deal.status_changedA deal transitioned to a new status
deal.closedA deal was closed
deal.fulfilledA deal was fulfilled
deal.expiredA deal expired without being completed
deal.unsignedA deal's signature was removed
deal.signature_addedA signature was added to a deal
deal.signature_timeoutA deal's signature request timed out
deal.item_addedA line item was added to a deal
deal.item_removedA line item was removed from a deal
deal.item_updatedA line item on a deal was updated
deal.discount_appliedA discount was applied to a deal
deal.partially_acceptedA deal was partially accepted by the customer
deal.created_configuredA deal was created from a saved product configuration
deal.payment_receivedA payment was received for a deal
deal.payment_failedA payment attempt failed
deal.payment_refundedA payment was refunded (full or partial)
deal.payment_overdueA payment is overdue
deal.settlement_createdA settlement was created for a deal
deal.settlement_initiatedA settlement was initiated
deal.settlement_completedA settlement completed successfully
deal.settlement_failedA settlement failed
deal.settlement_all_completedAll settlements for a deal completed
deal.participant_invitedA participant was invited to a deal
deal.participant_acceptedA participant accepted their deal invitation
deal.participant_withdrawnA participant withdrew from a deal
deal.participant_completedA participant completed their deal obligations
Negotiation Events — Legacy (deal.*) Maintained for backward compatibility. Both families fire simultaneously.
deal.negotiation_proposedA negotiation proposal was made (minimal payload)
deal.negotiation_counter_proposedA counter-proposal was made (minimal payload)
deal.negotiation_acceptedA negotiation proposal was accepted (minimal payload)
deal.negotiation_rejectedA negotiation proposal was rejected (minimal payload)
Negotiation Events — Current (negotiation.*) Richer payloads. Prefer these for new integrations.
negotiation.proposedInitial proposal submitted — includes proposer, terms, and expires_at
negotiation.counteredCounter-proposal made — includes round_number, previous_terms, and new_terms for diffing
negotiation.acceptedProposal accepted — includes final_terms and total_rounds
negotiation.rejectedProposal rejected — includes reason and round_number
negotiation.expiredA negotiation round expired without resolution
negotiation.suggestion_generatedAI generated a negotiation suggestion
Contract Events
contract.signedA contract was signed
contract.activatedA contract was activated
contract.terminatedA contract was terminated
contract.tamper_detectedA tamper attempt was detected on a contract
contract.auto_renewedA contract was automatically renewed
contract.renewal_failedA contract auto-renewal attempt failed
contract.renewal_opted_outA customer opted out of contract auto-renewal
contract.renewal_upcomingA contract renewal is approaching
Subscription Events
subscription.createdA subscription was created
subscription.renewedA subscription was renewed
subscription.renewal_upcomingA subscription renewal is approaching
subscription.pausedA subscription was paused
subscription.resumedA paused subscription was resumed
subscription.cancelledA subscription was cancelled
subscription.upgradedA subscription was upgraded to a higher tier
subscription.downgradedA subscription was downgraded to a lower tier
subscription.changedA subscription was modified
subscription.past_dueA subscription payment is past due
subscription.suspendedA subscription was suspended due to non-payment
subscription.cycle_changedA subscription billing cycle was changed
subscription.payment_failedA subscription payment attempt failed
subscription.payment_retriedA failed subscription payment was retried
subscription.proration_creditA proration credit was applied to a subscription
subscription.meter_addedA usage meter was added to a subscription
subscription.meter_removedA usage meter was removed from a subscription
subscription.usage_recordedUsage was recorded against a subscription meter
subscription.usage_charges_appliedUsage charges were applied to a subscription
Customer Events
customer.createdA new customer was created
customer.updatedA customer record was updated
customer.deletedA customer was deleted
Booking Events
booking.createdA new booking was created
booking.cancelledA booking was cancelled
booking.completedA booking was completed
booking.no_showA customer did not show up for a booking
booking.heldA booking slot was placed on hold
booking.hold_expiredA booking hold expired without confirmation
booking.rescheduledA booking was rescheduled to a new time
Billing Events
billing.credit_addedCredits were added to the account balance
billing.credit_deductedCredits were deducted from the account balance
billing.auto_topupAn automatic top-up was triggered
billing.low_balanceAccount credit balance dropped below the threshold
billing.widget_degradedThe widget entered degraded mode due to insufficient credits
Delegation Events
delegation.proposedA delegation proposal was submitted
delegation.acceptedA delegation proposal was accepted
delegation.rejectedA delegation proposal was rejected
delegation.counteredA counter-proposal was made to a delegation
delegation.grantedA delegation was granted to an agent
delegation.revokedA delegation was revoked
delegation.expiredA delegation expired
delegation.budget_warningA delegation is approaching its budget limit
Agent Events
agent.approval_requiredAn agent action requires human approval
agent.approval_resentAn approval request was resent
agent.approval_escalatedAn approval request was escalated
agent.anomaly_detectedAnomalous agent behaviour was detected
agent.spending_ceilingAn agent reached its spending ceiling
agent.trust_cap_exceededAn agent exceeded its trust cap
agent.trust.level_changedAn agent's trust level changed
agent.trust.abuse_detectedAbuse was detected from a trusted agent
agent.trust.decay_warningAn agent's trust score is decaying
agent.trust.credential_issuedA trust credential was issued to an agent
agent.trust.credential_presentedAn agent presented a trust credential
agent.trust.credential_revokedAn agent's trust credential was revoked
Agent Workflow Events
agent.workflow.plannedAn agent workflow plan was created
agent.workflow.approvedAn agent workflow was approved to proceed
agent.workflow.completedAn agent workflow completed successfully
agent.workflow.failedAn agent workflow failed
agent.workflow.cancelledAn agent workflow was cancelled
agent.workflow.degradedAn agent workflow entered degraded mode
agent.workflow.step_completedA step in an agent workflow completed
agent.workflow.step_retriedA workflow step was retried
agent.workflow.dead_letteredA workflow step was moved to the dead-letter queue
Escrow Events
escrow.createdAn escrow was created
escrow.releasedAn escrow was released
escrow.refundedAn escrow was refunded
escrow.condition_fulfilledAn escrow condition was fulfilled
escrow.reauthorization_pendingAn escrow requires reauthorization
escrow.reauthorizedAn escrow was successfully reauthorized
escrow.reauthorization_failedAn escrow reauthorization attempt failed
Federation Events
federation.settlement_completedA cross-tenant federated settlement completed
federation.settlement_failedA cross-tenant federated settlement failed
federation.escrow_disputedA federated escrow was disputed
federation.escrow_expiredA federated escrow expired
Product & Catalogue Events
product_family.createdA product family was created
product_family.updatedA product family was updated
product_family.deletedA product family was deleted
option_group.createdAn option group was created
option_group.updatedAn option group was updated
option_group.deletedAn option group was deleted
option.createdA product option was created
option.updatedA product option was updated
option.deletedA product option was deleted
bundle_rule.createdA bundle rule was created
bundle_rule.updatedA bundle rule was updated
bundle_rule.deletedA bundle rule was deleted
compatibility_rule.createdA compatibility rule was created
compatibility_rule.updatedA compatibility rule was updated
compatibility_rule.deletedA compatibility rule was deleted
Saved Configuration Events
saved_config.createdA product configuration was saved
saved_config.viewedA saved configuration was viewed
saved_config.convertedA saved configuration was converted to a deal
saved_config.expiringA saved configuration is about to expire
saved_config.expiredA saved configuration expired
Portal Events
portal.payment_completedA payment was completed via the customer portal
portal.contract_signedA contract was signed via the customer portal
portal.change_requestedA change was requested via the customer portal
Consent Events
consent.expiring_soonA customer consent record is about to expire
consent.expiredA customer consent record expired
Tenant & Trust Events
tenant.trust_level_changedA tenant's trust level changed
tenant.trust_promotedA tenant was promoted to a higher trust tier
tenant.trust_level_decay_warningA tenant's trust level is decaying
trust.demotedA trust entity was demoted to a lower tier
trust.fraud_signalA fraud signal was raised against a trust entity
Workflow Events
workflow.step_approvedA workflow step was approved
workflow.sell.proposal_receivedA sell workflow received a proposal
workflow.fulfill.deliveredA fulfillment workflow delivered its outcome
System & Infrastructure Events
job.completedA background job completed
job.failedA background job failed
queue.depth_alertA job queue depth exceeded its alert threshold
system.job_dead_letterA job was moved to the dead-letter queue
service.circuit_openedA circuit breaker opened due to repeated failures
service.circuit_closedA circuit breaker closed after recovery
circuit-breaker.backoff-increasedA circuit breaker increased its backoff interval
encryption.rekey_completedAn encryption re-key operation completed
security.csp_spikeA spike in CSP violation reports was detected
Other Events
payment.receivedA payment was received
credential.issuedA verifiable credential was issued
api_key.rotatedAn API key was rotated

Webhook Payload Format

All webhook payloads follow the same structure. Each delivery includes an X-Salesbooth-Signature header for verification.

Example Payload — deal.created
{ "id": "evt_abc123", "event": "deal.created", "created_at": "2026-03-09T10:30:00Z", "data": { "id": "deal_abc123", "customer_id": "cust_xxxxx", "status": "draft", "currency": "USD", "subtotal": "0.00", "total": "0.00", "created_at": "2026-03-09T10:30:00Z" } }
Example Payload — deal.status_changed
{ "id": "evt_def456", "event": "deal.status_changed", "created_at": "2026-03-09T11:00:00Z", "data": { "id": "deal_abc123", "previous_status": "draft", "new_status": "in_progress", "changed_at": "2026-03-09T11:00:00Z" } }
Example Payload — deal.payment_received
{ "id": "evt_ghi789", "event": "deal.payment_received", "created_at": "2026-03-09T12:00:00Z", "data": { "deal_id": "deal_abc123", "amount": "1099.00", "currency": "USD", "payment_intent_id": "pi_xxxxx", "status": "succeeded" } }
Example Payload — customer.created
{ "id": "evt_jkl012", "event": "customer.created", "created_at": "2026-03-09T10:00:00Z", "data": { "id": "cust_xxxxx", "company": "Acme Corp", "status": "active", "created_at": "2026-03-09T10:00:00Z" } }
Example Payload — contract.signed
{ "id": "evt_mno345", "event": "contract.signed", "created_at": "2026-03-09T13:00:00Z", "data": { "id": "contract_xxxxx", "deal_id": "deal_abc123", "customer_id": "cust_xxxxx", "signed_by": "customer", "signed_at": "2026-03-09T13:00:00Z", "signature_method": "ed25519" } }
Example Payload — negotiation.proposed
{ "id": "evt_pqr678", "event": "negotiation.proposed", "created_at": "2026-03-09T14:00:00Z", "data": { "deal_id": "deal_abc123", "round_number": 1, "proposer": "agent", "proposed_terms": { "discount_percent": 15, "payment_terms": "net_30" }, "message": "Volume order — requesting 15% discount", "expires_at": "2026-03-16T14:00:00Z" } }
Example Payload — negotiation.countered
{ "id": "evt_stu901", "event": "negotiation.countered", "created_at": "2026-03-09T15:00:00Z", "data": { "deal_id": "deal_abc123", "round_number": 2, "proposer": "merchant", "previous_terms": { "discount_percent": 15, "payment_terms": "net_30" }, "new_terms": { "discount_percent": 10, "payment_terms": "net_15" }, "message": "We can offer 10% with net-15 terms", "expires_at": "2026-03-18T15:00:00Z" } }
Example Payload — negotiation.accepted
{ "id": "evt_vwx234", "event": "negotiation.accepted", "created_at": "2026-03-09T16:00:00Z", "data": { "deal_id": "deal_abc123", "total_rounds": 2, "final_terms": { "discount_percent": 10, "payment_terms": "net_15" }, "accepted_by": "agent", "accepted_at": "2026-03-09T16:00:00Z" } }
Example Payload — subscription.created
{ "id": "evt_yza567", "event": "subscription.created", "created_at": "2026-03-09T17:00:00Z", "data": { "deal_id": "deal_abc123", "billing_cycle": "monthly", "status": "active", "next_renewal_at": "2026-04-09T17:00:00Z", "amount": "99.00", "currency": "USD" } }
Example Payload — subscription.past_due
{ "id": "evt_bcd890", "event": "subscription.past_due", "created_at": "2026-04-09T17:05:00Z", "data": { "deal_id": "deal_abc123", "amount": "99.00", "currency": "USD", "failure_reason": "card_declined", "grace_period_ends_at": "2026-04-16T17:05:00Z", "retry_count": 1 } }
Example Payload — escrow.created
{ "id": "evt_efg123", "event": "escrow.created", "created_at": "2026-03-10T10:00:00Z", "data": { "id": "escrow_xxxxx", "deal_id": "deal_abc123", "amount": "2500.00", "currency": "USD", "release_condition": "delivery_confirmed", "expires_at": "2026-06-10T10:00:00Z" } }
Example Payload — subscription.renewed
{ "id": "evt_hij456", "event": "subscription.renewed", "created_at": "2026-04-09T17:00:00Z", "data": { "deal_id": "deal_abc123", "renewal_deal_id": "deal_def456", "billing_cycle": "monthly", "base_amount": "99.00", "metered_amount": "2.55", "total_amount": "101.55", "currency": "USD", "next_renewal_at": "2026-05-09T17:00:00Z" } }
Example Payload — subscription.cancelled
{ "id": "evt_klm789", "event": "subscription.cancelled", "created_at": "2026-03-12T10:00:00Z", "data": { "deal_id": "deal_abc123", "cancelled_at": "2026-03-12T10:00:00Z", "effective_at": "2026-04-09T17:00:00Z", "end_of_period": true, "reason": "Customer requested cancellation" } }

Signature Verification

Every webhook delivery includes two headers: X-Salesbooth-Signature (v1= + HMAC-SHA256 of the timestamp + raw body) and X-Salesbooth-Timestamp (Unix timestamp of delivery). Always verify both to prevent replay attacks. Reject events where the timestamp is older than 300 seconds (5 minutes).

const crypto = require('crypto'); const TOLERANCE_SECONDS = 300; // 5 minutes function verifyWebhook(rawBody, signature, timestamp, secret) { // 1. Reject stale events const age = Math.floor(Date.now() / 1000) - parseInt(timestamp, 10); if (age > TOLERANCE_SECONDS) throw new Error('Webhook timestamp too old'); // 2. Compute expected signature: v1= + HMAC-SHA256(timestamp.body, secret) const payload = `${timestamp}.${rawBody}`; const expected = 'v1=' + crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); // 3. Constant-time comparison (signature starts with "v1=" — not valid hex) if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) throw new Error('Invalid signature'); return true; } // Express.js example app.post('/webhooks/salesbooth', express.raw({ type: 'application/json' }), (req, res) => { try { verifyWebhook( req.body.toString(), req.headers['x-salesbooth-signature'], req.headers['x-salesbooth-timestamp'], process.env.WEBHOOK_SECRET ); const event = JSON.parse(req.body); console.log('Verified event:', event.event, event.id); res.sendStatus(200); } catch (err) { console.error('Webhook verification failed:', err.message); res.sendStatus(400); } });

Audit Trail

Every entity has an immutable, cryptographically chained audit trail. Entries cannot be modified or deleted.

GET /api/v1/audit?entity_type={type}&entity_id={id}
Retrieve the audit trail for an entity.
ParameterDescription
entity_type requireddeal, contract, customer, product
entity_id requiredThe entity identifier
limitMax results, 1–100 (default: 50)
offsetPagination offset
GET /api/v1/audit?entity_type={type}&entity_id={id}&action=verify
Verify the cryptographic hash chain integrity of an audit trail. Returns whether all entries are intact and untampered.
GET /api/v1/audit/export
Export the audit trail as a self-contained compliance evidence package. Requires the audit:export scope. Supports three export modes: single entity (provide entity_type + entity_id), date range (provide start_date + end_date), or bulk by type (provide entity_type alone). Exports include a verification_hash (SHA-256) covering the entire payload for tamper detection. Use format=csv to receive a spreadsheet-compatible download.
ParameterTypeDescription
entity_typestringdeal, contract, customer, or product
entity_idstringSpecific entity ID (required with entity_type for single-entity export)
start_datestringStart of date range (Y-m-d or Y-m-d H:i:s)
end_datestringEnd of date range (Y-m-d or Y-m-d H:i:s)
formatstringjson (default) or csv
limitintegerMax entries to return, 1–10000 (default: 1000)
offsetintegerPagination offset
Single entity export
curl "https://salesbooth.com/api/v1/audit/export?entity_type=deal&entity_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Date range export (CSV)
curl "https://salesbooth.com/api/v1/audit/export?start_date=2026-01-01&end_date=2026-03-31&format=csv" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -o audit-q1-2026.csv
Response (JSON)
{ "error": false, "data": { "export_version": "1.0", "exported_at": "2026-03-18T10:00:00Z", "tenant_id": "tenant_xxxxx", "entity_type": "deal", "entity_id": "deal_abc123", "audit_entries": [ { "id": "audit_001", "action": "deal.created", "actor": "user_xxxxx", "created_at": "2026-03-10T09:00:00Z", "entry_hash": "b4e2a1..." } ], "verification_hash": "sha256:c9f3b2..." } }

Intelligence

AI-powered deal scoring, pricing analytics, risk assessment, pipeline forecasting, and model calibration. All endpoints require the deals:read scope; config write operations additionally require intelligence:write.

Scoring model: Each deal score (0–100) is a weighted composite of configurable factors. Default weights: deal_size (25%), customer_history (30%), pipeline_stage (20%), engagement (15%), time_in_stage (10%). Weights must sum to 1.0 and can be overridden per tenant via PATCH ?type=config.

GET /api/v1/intelligence?type=score&deal_id={deal_id}
AI-generated deal score (0–100) with factor breakdown, recommendations, and risk flags.
ParameterTypeDescription
deal_id requiredstringThe deal to score
Example
curl "https://salesbooth.com/api/v1/intelligence?type=score&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "score": 74, "confidence": "high", "label": "Good", "factors": { "deal_size": { "score": 80, "weight": 0.25, "contribution": 20 }, "customer_history": { "score": 70, "weight": 0.30, "contribution": 21 }, "pipeline_stage": { "score": 60, "weight": 0.20, "contribution": 12 }, "engagement": { "score": 85, "weight": 0.15, "contribution": 12.75 }, "time_in_stage": { "score": 67, "weight": 0.10, "contribution": 6.7 } }, "recommendations": [ { "type": "discount", "amount": 5, "rationale": "Volume threshold reached — 5% discount increases close probability by ~12%" } ], "risk_flags": [], "scored_at": "2026-03-12T10:00:00Z" } }
GET /api/v1/intelligence?type=pricing_suggestion&deal_id={deal_id}
AI-suggested optimal price for a deal based on comparable historical deals, customer segment, and pipeline data.
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "suggested_price": 4750.00, "current_price": 5000.00, "confidence": "medium", "rationale": "Similar deals with this customer segment close 23% more often at 4,500–5,000 range", "comparable_deals": 47, "win_rate_at_suggested": 0.71, "win_rate_at_current": 0.58 } }
GET /api/v1/intelligence?type=risk&deal_id={deal_id}
Risk assessment for a specific deal. Returns identified risk factors, severity levels, and mitigation suggestions.
Example
curl "https://salesbooth.com/api/v1/intelligence?type=risk&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "overall_risk": "medium", "risk_score": 42, "factors": [ { "factor": "time_in_stage", "severity": "high", "description": "Deal has been in 'in_progress' for 18 days (median: 7 days)", "mitigation": "Follow up with customer — consider offering a limited-time incentive" }, { "factor": "deal_size", "severity": "low", "description": "Deal value is within normal range for this customer segment", "mitigation": null } ], "churn_probability": 0.31, "assessed_at": "2026-03-12T10:00:00Z" } }
GET /api/v1/intelligence?type=close_forecast&deal_id={deal_id}
Predicted close date and probability distribution for a specific deal based on pipeline velocity and historical patterns.
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "predicted_close_date": "2026-04-08", "confidence_interval": { "p25": "2026-03-28", "p50": "2026-04-08", "p75": "2026-04-22" }, "close_probability_30d": 0.68, "close_probability_60d": 0.84, "methodology": "Gradient boosted on 2,400 historical deals in this pipeline stage" } }
GET /api/v1/intelligence?type=pipeline_forecast
Aggregate revenue forecast for all active pipeline deals. Sums probability-weighted close amounts by period.
ParameterTypeDescription
periodstring30d, 60d, 90d, or all (default: all)
Response
{ "error": false, "data": { "period": "90d", "forecast_revenue": 284500.00, "weighted_pipeline": 142750.00, "currency": "USD", "by_stage": { "in_progress": { "count": 23, "total_value": 187000.00, "weighted": 93500.00 }, "pending_signature": { "count": 8, "total_value": 97500.00, "weighted": 87750.00 } }, "generated_at": "2026-03-12T10:00:00Z" } }
GET /api/v1/intelligence?type=win_probability_curve
Win probability calibration curve — maps deal scores to observed win rates. Use this to understand how accurate the scoring model is for your data.
Response
{ "error": false, "data": { "buckets": [ { "score_range": "0-20", "avg_score": 12, "win_rate": 0.08, "sample_size": 34 }, { "score_range": "21-40", "avg_score": 31, "win_rate": 0.22, "sample_size": 67 }, { "score_range": "41-60", "avg_score": 51, "win_rate": 0.45, "sample_size": 112 }, { "score_range": "61-80", "avg_score": 71, "win_rate": 0.69, "sample_size": 89 }, { "score_range": "81-100","avg_score": 88, "win_rate": 0.86, "sample_size": 54 } ], "calibration_error": 0.04, "total_deals": 356 } }
GET /api/v1/intelligence?type=score_history&deal_id={deal_id}
Historical scoring snapshots for a deal. Useful for charting score trends and correlating score changes with deal events.
ParameterTypeDescription
deal_id requiredstringThe deal to fetch history for
limitintegerMax snapshots (default: 20)
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "history": [ { "score": 62, "scored_at": "2026-03-01T09:00:00Z", "trigger": "deal_created" }, { "score": 68, "scored_at": "2026-03-05T14:30:00Z", "trigger": "item_added" }, { "score": 74, "scored_at": "2026-03-09T10:00:00Z", "trigger": "negotiation_accepted" } ] } }
GET /api/v1/intelligence?type=score_accuracy
Model calibration report for the current scoring configuration. Returns accuracy metrics and weight optimization suggestions based on your tenant’s deal history.
Response
{ "error": false, "data": { "accuracy": 0.79, "brier_score": 0.14, "deals_analyzed": 356, "current_weights": { "deal_size": 0.25, "customer_history": 0.30, "pipeline_stage": 0.20, "engagement": 0.15, "time_in_stage": 0.10 }, "suggested_weights": { "deal_size": 0.20, "customer_history": 0.35, "pipeline_stage": 0.25, "engagement": 0.10, "time_in_stage": 0.10 }, "estimated_accuracy_improvement": 0.04 } }
GET /api/v1/intelligence?type=pricing
Pricing intelligence across all products — average deal sizes, price distribution, and discount patterns by product.
Example
curl "https://salesbooth.com/api/v1/intelligence?type=pricing" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/intelligence?type=pipeline
Pipeline analytics — deals by stage, conversion rates, average time-in-stage, and velocity metrics.
GET /api/v1/intelligence?type=outcome_analytics
Deal outcome analytics — win/loss rates, average deal size by outcome, revenue attributed, and time-to-close by segment.
GET /api/v1/intelligence?type=loss_patterns
Common patterns in lost deals. Clusters similar loss reasons to identify systemic issues (e.g. price too high, slow response, competitor).
GET /api/v1/intelligence?type=config
Get the current scoring configuration (weights, thresholds, enabled factors).
PATCH /api/v1/intelligence?type=config
Update deal scoring weights and thresholds. Requires intelligence:write scope. Weights must sum to 1.0.
FieldTypeDescription
weightsobjectKeys: deal_size, customer_history, pipeline_stage, engagement, time_in_stage. Values must sum to 1.0.
thresholdsobjectScore thresholds for label assignment: good (default: 70), fair (default: 40), poor (below 40)
Example
curl -X PATCH "https://salesbooth.com/api/v1/intelligence?type=config" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "weights": { "deal_size": 0.20, "customer_history": 0.35, "pipeline_stage": 0.25, "engagement": 0.10, "time_in_stage": 0.10 }, "thresholds": { "good": 72, "fair": 45 } }'
POST /api/v1/intelligence?type=backtest
Backtest proposed scoring weights against your historical deal data before applying them. Returns accuracy comparison between proposed and current configuration.
FieldTypeDescription
weights requiredobjectProposed weight configuration to test (must sum to 1.0)
Example
curl -X POST "https://salesbooth.com/api/v1/intelligence?type=backtest" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "weights": { "deal_size": 0.20, "customer_history": 0.35, "pipeline_stage": 0.25, "engagement": 0.10, "time_in_stage": 0.10 } }'
Response
{ "error": false, "data": { "proposed_accuracy": 0.83, "current_accuracy": 0.79, "improvement": 0.04, "deals_tested": 356, "top_gains": [ { "stage": "pending_signature", "accuracy_delta": 0.09 } ] } }
GET /api/v1/intelligence?type=pipeline_deals&stage={stage}
Returns all deals within a specific pipeline stage, enriched with the latest AI score and win probability. Useful for building stage-level kanban views or identifying high-value deals that need attention.
ParameterTypeDescription
stage requiredstringPipeline stage to query. One of: draft, in_progress, pending_payment, pending_signature, awaiting_signatures, closed, cancelled, expired
Example
curl "https://salesbooth.com/api/v1/intelligence?type=pipeline_deals&stage=in_progress" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "stage": "in_progress", "count": 3, "deals": [ { "deal_id": "deal_abc123", "title": "Enterprise Plan — Acme Corp", "total": 12500.00, "status": "in_progress", "created_at": "2026-03-01T09:00:00Z", "customer_name": "Acme Corp", "score": 74, "win_probability": 0.68, "days_since_update": 3 } ] } }
GET /api/v1/intelligence?type=pricing_suggestions_bulk
Bulk pricing suggestions for all active deals that are currently under-discounted compared to similar deals that closed successfully. Returns up to 20 deals ranked by priority (lowest win probability first). Only deals where the suggested discount is ≥5% and there are ≥3 comparable closed deals are included.
Example
curl "https://salesbooth.com/api/v1/intelligence?type=pricing_suggestions_bulk" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "count": 2, "suggestions": [ { "deal_id": "deal_abc123", "title": "Enterprise Plan — Acme Corp", "total": 12500.00, "currency": "USD", "product_name": "Enterprise Plan", "current_discount": 0, "suggested_discount": 8.5, "avg_winning_discount": 8.5, "win_probability": 0.42, "probability_lift": 0.034, "score": 51, "reason": "Products like \"Enterprise Plan\" close at 8.5% avg discount on similar deals" } ] } }
GET /api/v1/intelligence?type=suggestion_analytics
Analytics on AI suggestion acceptance and rejection rates. Shows which suggestion types are being acted on, their impact on deal outcomes, and trends over time. Use this to evaluate the effectiveness of AI recommendations for your pipeline.
ParameterTypeDescription
daysintegerLookback window in days, 7–365 (default: 90)
Example
curl "https://salesbooth.com/api/v1/intelligence?type=suggestion_analytics&days=90" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "period_days": 90, "total_suggestions": 148, "accepted": 62, "rejected": 41, "pending": 45, "acceptance_rate": 0.60, "by_type": { "discount": { "total": 89, "accepted": 41, "acceptance_rate": 0.62 }, "follow_up": { "total": 35, "accepted": 14, "acceptance_rate": 0.54 }, "upsell": { "total": 24, "accepted": 7, "acceptance_rate": 0.44 } }, "outcome_impact": { "accepted_deal_win_rate": 0.71, "rejected_deal_win_rate": 0.48 } } }
GET /api/v1/intelligence?type=counter_terms&deal_id={deal_id}
AI-suggested counter-terms for deal negotiations. Analyses the current deal terms and buyer history to recommend revised terms that balance win probability with revenue protection. Particularly useful in agent integrations and automated negotiation workflows.
ParameterTypeDescription
deal_id requiredstringThe deal to generate counter-terms for
current_termsstringJSON-encoded object of the buyer's proposed terms to counter (optional). If omitted, suggestions are based on the deal's current state.
Example
curl "https://salesbooth.com/api/v1/intelligence?type=counter_terms&deal_id=deal_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Example with buyer terms
curl -G "https://salesbooth.com/api/v1/intelligence" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ --data-urlencode "type=counter_terms" \ --data-urlencode "deal_id=deal_abc123" \ --data-urlencode 'current_terms={"discount_pct":15,"payment_terms":"net60"}'
Response
{ "error": false, "data": { "deal_id": "deal_abc123", "counter_terms": [ { "field": "discount_pct", "buyer_proposed": 15, "counter_offer": 8, "rationale": "8% is within the range that closes 73% of deals in this segment; 15% reduces margin below threshold" }, { "field": "payment_terms", "buyer_proposed": "net60", "counter_offer": "net30", "rationale": "net30 is standard for this customer tier; offer net45 as a concession if needed" } ], "win_probability_if_accepted": 0.71, "generated_at": "2026-03-12T10:00:00Z" } }

SDK Example — Score a Deal

const { SalesBooth } = require('@salesbooth/node'); const sb = new SalesBooth({ apiKey: 'sb_test_example_key_do_not_use' }); // Score a deal and get recommendations const result = await sb.intelligence.score('deal_abc123'); console.log('Score:', result.data.score); // 74 console.log('Confidence:', result.data.confidence); // "high" result.data.recommendations.forEach(rec => { console.log(`Recommendation: ${rec.type} ${rec.amount}% — ${rec.rationale}`); }); // Get pricing suggestion const suggestion = await sb.intelligence.pricingSuggestion('deal_abc123'); console.log('Suggested price:', suggestion.data.suggested_price); // Get risk assessment const risk = await sb.intelligence.risk('deal_abc123'); if (risk.data.overall_risk === 'high') { console.warn('High-risk deal:', risk.data.factors.map(f => f.factor)); }

Activity Feed

Real-time event log and notification management. The activity feed records all significant events across deals, customers, payments, and more. Configure notification rules to route alerts to email, webhook, or in-app channels.

GET /api/v1/activity
List activity feed events with optional filters.
ParameterTypeDescription
event_typestringFilter by event type (e.g. deal.created, payment.received)
actor_typestringFilter by actor: user, agent, or system
entity_typestringFilter by entity: deal, contract, customer
limitintegerMax results (default: 50, max: 100)
offsetintegerPagination offset
Example
curl "https://salesbooth.com/api/v1/activity?event_type=deal.created&limit=20" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/activity?action=notifications
List in-app notifications for the current user.
Example
curl "https://salesbooth.com/api/v1/activity?action=notifications" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/activity?action=rules
List notification rules. Rules define which events trigger notifications and where they are sent.
Example
curl "https://salesbooth.com/api/v1/activity?action=rules" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/activity?action=create_rule
Create a notification rule.
FieldTypeDescription
event_type requiredstringEvent pattern to match (e.g. deal.signature_added, payment.*)
channel requiredstringDelivery channel: email, webhook, or in_app
namestringRule display name
Example
curl -X POST "https://salesbooth.com/api/v1/activity?action=create_rule" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "event_type": "deal.signature_added", "channel": "email", "name": "Notify on deal sign" }'
POST /api/v1/activity?action=mark_read
Mark specific notifications as read. Use action=mark_all_read to mark all as read at once.
FieldTypeDescription
notification_ids requiredarrayArray of notification IDs to mark as read
Example
curl -X POST "https://salesbooth.com/api/v1/activity?action=mark_read" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "notification_ids": ["notif_abc", "notif_def"] }'
PATCH /api/v1/activity?action=update_rule&rule_id={rule_id}
Update an existing notification rule.
Example
curl -X PATCH "https://salesbooth.com/api/v1/activity?action=update_rule&rule_id=rule_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "channel": "webhook" }'
DELETE /api/v1/activity?action=delete_rule&rule_id={rule_id}
Delete a notification rule.
Example
curl -X DELETE "https://salesbooth.com/api/v1/activity?action=delete_rule&rule_id=rule_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/activity?action=preferences
Retrieve the current user’s activity notification preferences. Returns per-event-type channel settings (email, in-app, webhook).
Example
curl "https://salesbooth.com/api/v1/activity?action=preferences" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deal.created": { "email": true, "in_app": true, "webhook": false }, "deal.signature_added": { "email": true, "in_app": true, "webhook": true }, "payment.received": { "email": true, "in_app": false, "webhook": true } } }
PUT /api/v1/activity?action=preferences
Save the current user’s activity notification preferences. Replaces all preferences for the authenticated user. Send the full preferences object keyed by event type.
Example
curl -X PUT "https://salesbooth.com/api/v1/activity?action=preferences" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal.created": { "email": true, "in_app": true, "webhook": false }, "deal.signature_added": { "email": true, "in_app": true, "webhook": true }, "payment.received": { "email": false, "in_app": true, "webhook": true } }'

Batch Operations

Execute up to 25 API operations in a single request. All operations run inside a transaction — if any write fails, all mutations are rolled back. Ideal for reducing round-trips in integrations and complex workflows.

Transactional. All write operations in a batch are atomic. Any failure rolls back all mutations. Read operations (GET) are always included in the response regardless of write failures.

POST /api/v1/batch
Execute multiple API operations in a single transactional request. Each operation specifies a method, resource, optional id, optional body, and optional version for optimistic locking.
FieldTypeDescription
operations requiredarrayArray of operation objects (max 25). Supported resources: deals, customers, products, contracts
Example
curl -X POST https://salesbooth.com/api/v1/batch \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "operations": [ { "method": "POST", "resource": "customers", "body": { "name": "Acme Corp" } }, { "method": "POST", "resource": "deals", "body": { "title": "Enterprise Plan", "amount": 5000 } }, { "method": "PATCH", "resource": "deals", "id": "deal_existing", "body": { "status": "active" }, "version": 3 } ] }'
Response
{ "error": false, "data": { "results": [ { "index": 0, "status": 201, "data": { "id": "cust_xxxxx" } }, { "index": 1, "status": 201, "data": { "id": "deal_xxxxx" } }, { "index": 2, "status": 200, "data": { "id": "deal_existing" } } ], "committed": true } }

AI Agent Integration

Salesbooth provides first-class support for AI agents through tool schemas, MCP protocol, and an agent SDK. Agents can discover, negotiate, and execute deals automatically.

Tool Definitions

The /api/v1/tools endpoint returns curated tool definitions optimized for LLM function-calling. Each tool maps to a high-level business operation.

GET /api/v1/tools
List agent tool definitions. Supports OpenAI, Anthropic, and universal formats.
ParameterDescription
formatuniversal (default), openai, or anthropic
categoryFilter: discovery, deals, products, negotiation, execution
Example: OpenAI Function-Calling
curl https://salesbooth.com/api/v1/tools?format=openai \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Available Tools

ToolCategoryDescription
discover_dealsDiscoveryFind available deals matching criteria
list_productsDiscoveryBrowse products and configurations
get_deal_terms_schemaDiscoveryGet the deal terms JSON Schema
configure_productProductsValidate a product configuration
calculate_pricingProductsCalculate pricing for a configuration
create_dealDealsCreate a new deal
check_deal_statusDealsGet deal state and line items
update_dealDealsUpdate deal or transition status
search_dealsDealsSearch deals by criteria
negotiate_termsNegotiationPropose or counter-propose terms
get_negotiation_historyNegotiationView negotiation rounds
accept_dealExecutionAccept and close a deal
sign_contractExecutionDigitally sign deal terms

MCP Server

The /api/v1/mcp endpoint implements the Model Context Protocol over HTTP using JSON-RPC 2.0.

POST /api/v1/mcp
MCP JSON-RPC endpoint. Supports initialize, tools/list, tools/call, resources/list, resources/read, and ping.
Example: MCP Initialize
curl -X POST https://salesbooth.com/api/v1/mcp \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{}}'
Example: List MCP Tools
curl -X POST https://salesbooth.com/api/v1/mcp \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":"2","method":"tools/list","params":{}}'

Agent SDK

The Agent SDK provides getToolDefinitions() and executeTool() for seamless LLM integration.

Node.js
const SalesboothAgent = require('./salesbooth-agent'); const agent = SalesboothAgent.init({ apiKey: 'sb_test_example_key_do_not_use', delegationId: 'del_xxxxx' // optional }); // Get tool definitions for OpenAI const tools = agent.getToolDefinitions('openai'); // Execute a tool const deals = await agent.executeTool('discover_deals', { category: 'software', max_price: 10000 });
Via the main SDK
const Salesbooth = require('salesbooth'); // Creates an agent client (requires salesbooth-agent.js) const agent = Salesbooth.agent({ apiKey: 'sb_test_example_key_do_not_use', delegationId: 'del_xxxxx' }); const tools = agent.getToolDefinitions('anthropic');

Agent Scopes

ScopeDescription
agent:discoverDiscover deals, browse products, and read tool definitions
agent:negotiatePropose, counter, accept, or reject deal terms
agent:executeCreate deals, sign contracts, and close deals
agent:*All agent scopes

Delegation Tokens

Use delegation tokens to grant agents scoped access with spending limits. Pass the delegation ID via the X-Delegation-ID header.

Example: Agent with Delegation
curl https://salesbooth.com/api/v1/tools \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "X-Delegation-ID: del_xxxxx"

Agent Discovery

Merchant control plane for AI-visible offers. Toggle product discoverability, manage pricing rules for agents, and view agent analytics.

GET /api/v1/agent-discovery-admin?action=dashboard
Get the agent discovery dashboard with product visibility stats, agent deal counts, and conversion metrics.
Example
curl https://salesbooth.com/api/v1/agent-discovery-admin?action=dashboard \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/agent-discovery-admin?action=products
List products with their agent discoverability status.
Example
curl https://salesbooth.com/api/v1/agent-discovery-admin?action=products \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/agent-discovery-admin?action=toggle
Toggle a product’s visibility to AI agents.
FieldTypeDescription
product_id requiredstringProduct to toggle
enabled requiredbooleanWhether agents can discover this product
Example
curl -X POST https://salesbooth.com/api/v1/agent-discovery-admin?action=toggle \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_xxxxx", "enabled": true }'
POST /api/v1/agent-discovery-admin?action=bulk-toggle
Bulk toggle discoverability for multiple products at once.
FieldTypeDescription
product_ids requiredarrayArray of product IDs
enabled requiredbooleanDiscoverability status
Example
curl -X POST https://salesbooth.com/api/v1/agent-discovery-admin?action=bulk-toggle \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_ids": ["prod_aaa", "prod_bbb"], "enabled": true }'

Agent Workflows

Autonomous deal orchestration. Agents can plan and execute multi-step deal workflows within delegation spending limits.

GET /api/v1/agent-workflow
List agent workflows or retrieve a specific workflow with its execution history.
ParameterTypeDescription
idstringRetrieve a specific workflow
statusstringFilter: planned, executing, completed, cancelled
delegation_idstringFilter by delegation
limitintegerMax results (default: 50)
Example
curl https://salesbooth.com/api/v1/agent-workflow?status=executing \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/agent-workflow
Plan a new workflow. The system generates a step-by-step execution plan based on the agent’s intent.
FieldTypeDescription
delegation_id requiredstringDelegation providing spending limits
intent requiredstringNatural language description of the workflow goal
constraintsobjectAdditional constraints (max_price, category, etc.)
Example
curl -X POST https://salesbooth.com/api/v1/agent-workflow \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "delegation_id": "del_xxxxx", "intent": "Find and negotiate the best enterprise software deal under $5000", "constraints": { "max_price": 5000, "category": "software" } }'
POST /api/v1/agent-workflow?id={workflow_id}&action=execute
Execute a planned workflow. Runs each step in sequence, checking delegation limits at each stage.
Example
curl -X POST "https://salesbooth.com/api/v1/agent-workflow?id=wf_xxxxx&action=execute" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/agent-workflow?id={workflow_id}&action=cancel
Cancel a workflow in progress.
Example
curl -X POST "https://salesbooth.com/api/v1/agent-workflow?id=wf_xxxxx&action=cancel" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Agent Trust

Per-API-key trust scoring, capability gating, and abuse protection. Agent trust levels determine transaction caps, allowed actions, and metered spending limits.

Who needs this: Agent Trust is relevant if you are building or integrating with autonomous AI agents that create or execute deals on behalf of users. Trust levels unlock higher transaction caps and advanced capabilities (delegation, federation) as an agent demonstrates a track record of reliable behaviour.

When to skip this: For standard server-side integrations using your own API key (not an agent key), trust levels do not apply. Human-driven integrations are not subject to trust caps.

Prerequisite: An agent API key (created with agent_key: true). Regular API keys are not subject to the trust tier system.

Trust Level Reference

LevelLabelTransaction CapCapabilitiesHow to Reach
0 Untrusted $0 — no transactions Read-only discovery Default for new API keys
1 Provisional $500 per deal Create deals, propose negotiations Score ≥ 20 — complete 1 deal
2 Established $5,000 per deal Full deal management, delegation Score ≥ 50 — complete 5 deals
3 Trusted Unlimited All capabilities, federation Score ≥ 80 — 30-day track record
4 Verified Partner Unlimited All + system-level tools Manual promotion by tenant admin

Trust Cap Exception: Attempting a deal above your transaction cap returns 403 trust_cap_exceeded. The response includes details.transaction_cap (your current limit) and details.attempted_amount. Complete more deals successfully to earn a higher trust level.

GET /api/v1/agent-trust
Get the current agent’s trust level, score, capabilities, and progress towards the next level.
ParameterTypeDescription
actionstringhistory for trust level change log, locks for active capability locks
limitintegerMax results for history (default: 50)
Example
curl https://salesbooth.com/api/v1/agent-trust \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "key_id": "key_abc123", "trust_level": 2, "trust_label": "Established", "score": 62, "transaction_cap": 5000, "capabilities": ["deal_management", "negotiation", "templates", "intelligence"], "locked_capabilities": [], "next_level": { "level": 3, "label": "Trusted", "score_needed": 80 }, "statistics": { "deals_completed": 7, "deals_failed": 0, "total_deal_value": 14350.00 } } }
GET /api/v1/agent-trust?action=history
Retrieve the trust level change history for the authenticated API key.
Example
curl "https://salesbooth.com/api/v1/agent-trust?action=history&limit=10" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Verifiable Credentials

Agents can receive verifiable W3C credentials attesting to their trust level and completed deal history. Credentials can be presented to third-party tenants during federation to establish cross-tenant trust without starting from level 0.

POST /api/v1/agent-trust-credentials
Issue a verifiable credential for the authenticated agent’s current trust level and statistics. The credential is signed with the tenant’s Ed25519 key and can be presented to other tenants.
Example
curl -X POST https://salesbooth.com/api/v1/agent-trust-credentials \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "credential_type": "TrustLevelCredential" }'
Response
{ "error": false, "data": { "credential_id": "cred_xyz789", "type": "TrustLevelCredential", "trust_level": 2, "issued_at": "2026-03-12T10:00:00Z", "expires_at": "2026-09-12T10:00:00Z", "jwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..." } }
GET /api/v1/agent-trust-credentials
List verifiable credentials issued to the authenticated agent.
Example
curl https://salesbooth.com/api/v1/agent-trust-credentials \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Trust-Related Webhook Events

agent.trust.level_changedTrust level promoted or demoted
agent.trust_cap_exceededAgent attempted a deal above their trust cap
agent.trust.abuse_detectedAnomalous behaviour detected — capability lock applied
agent.trust.credential_issuedVerifiable credential issued to agent
agent.trust.credential_revokedPreviously issued credential revoked

MCP Protocol

Salesbooth implements the Model Context Protocol (MCP) over HTTP using JSON-RPC 2.0. The MCP endpoint exposes 190 tools across 27 categories, resource browsing, prompt templates, and subscriptions — giving AI agents a structured, discoverable interface to the full Salesbooth platform.

Endpoint: POST https://salesbooth.com/api/v1/mcp

Protocol Version: 2024-11-05 — Server: salesbooth-mcp v2.0

Required scope: agent:discover (to connect). Individual tools require additional scopes — see the Scope Requirements table below.

1. Connection & Initialize Handshake

All MCP communication uses POST /api/v1/mcp with a JSON-RPC 2.0 body. Authenticate with your API key in the Authorization header. Begin every session with an initialize request to confirm capabilities.

POST /api/v1/mcp
MCP JSON-RPC 2.0 transport. All methods use this single endpoint. Supports initialize, tools/list, tools/call, resources/list, resources/templates/list, resources/read, resources/subscribe, resources/unsubscribe, prompts/list, prompts/get, and ping.
HeaderDescription
AuthorizationBearer <api_key> — required. Use an API key with at minimum agent:discover scope.
X-Delegation-IDOptional delegation token ID to execute tools under a scoped delegation with spending limits.
Content-Typeapplication/json
Initialize request
curl -X POST https://salesbooth.com/api/v1/mcp \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "initialize", "params": {} }'
Initialize response
{ "jsonrpc": "2.0", "id": "1", "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": { "listChanged": false }, "resources": { "subscribe": true, "listChanged": false }, "prompts": { "listChanged": false } }, "serverInfo": { "name": "salesbooth-mcp", "version": "2.0" } } }

2. Tool Discovery — tools/list

Retrieve the full catalogue of 156 agent tools. Each tool includes a JSON Schema for its parameters, making it directly consumable by LLM function-calling APIs (OpenAI, Anthropic, etc.).

Request
curl -X POST https://salesbooth.com/api/v1/mcp \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "2", "method": "tools/list", "params": {} }'
Response (excerpt — one tool shown)
{ "jsonrpc": "2.0", "id": "2", "result": { "tools": [ { "name": "discover_deals", "description": "Find available deals matching criteria. Returns deals that can be negotiated or accepted. Use this as the first step to find deals for a customer.", "inputSchema": { "type": "object", "properties": { "category": { "type": "string", "description": "Filter by product category" }, "min_price": { "type": "number" }, "max_price": { "type": "number" }, "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, "pricing_model": { "type": "string", "enum": ["one_time", "recurring", "usage_based", "tiered"] }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [], "additionalProperties": false } } // ... 155 more tools ] } }

Tool Categories

CategoryDescription
deal_managementCreate, update, and manage deals through their full lifecycle
product_catalogBrowse, configure, and manage products and pricing
customer_managementCreate and manage customer records
contractsCreate, sign, activate, and manage contracts
negotiationPropose, counter, and resolve deal negotiations
templatesCreate, clone, and instantiate deal templates
intelligenceAI-powered deal scoring, pricing analytics, and pipeline insights
paymentsProcess payments, refunds, and manual payment recordings
subscriptionsManage recurring billing subscriptions
widgetsConfigure and manage embeddable deal widgets
configurationManage product families, option groups, and pricing rules
saved_configsSave, share, and convert product configurations to deals
webhooksManage webhook endpoints and event delivery
delegationsCreate and manage agent delegation permissions
complianceGDPR operations and audit trail exports
searchGlobal search across customers, products, deals, and contracts
auditView and verify audit trails for entities
sandboxTest environment setup, seeding, and webhook simulation
workflowsAutonomous deal orchestration with delegation-scoped execution
agent_trustCheck trust level, capabilities, and trust lock status for the current agent
federationDiscover offerings on remote Salesbooth instances and negotiate cross-instance deals

3. Tool Execution — tools/call

Call any tool by name with its parameters. The server validates your scope, executes the tool, and returns structured JSON content. If a tool fails, isError is true and the content describes the error.

Request format
{ "jsonrpc": "2.0", "id": "<request_id>", "method": "tools/call", "params": { "name": "<tool_name>", "arguments": { /* tool parameters */ } } }
Success response format
{ "jsonrpc": "2.0", "id": "<request_id>", "result": { "content": [ { "type": "text", "text": "<JSON string of tool result>" } ], "isError": false } }

Workflow 1: Create a Deal from Products

Discover a customer → create a deal → add line items → transition to in_progress.

Step 1: Find the customer
{ "jsonrpc": "2.0", "id": "w1a", "method": "tools/call", "params": { "name": "search_customers", "arguments": { "query": "Acme Corp", "limit": 5 } } }
Step 2: Create the deal (scope: deals:write)
{ "jsonrpc": "2.0", "id": "w1b", "method": "tools/call", "params": { "name": "create_deal", "arguments": { "customer_id": "cust_abc123", "currency": "USD", "deal_type": "one_time", "description": "Enterprise software package" } } }
Step 3: Add a line item (scope: deals:write)
{ "jsonrpc": "2.0", "id": "w1c", "method": "tools/call", "params": { "name": "add_deal_item", "arguments": { "id": "deal_xyz789", "product_id": "prod_platform_pro", "quantity": 10, "unit_price": 99.00 } } }
Step 4: Transition to in_progress (scope: deals:write)
{ "jsonrpc": "2.0", "id": "w1d", "method": "tools/call", "params": { "name": "transition_deal", "arguments": { "id": "deal_xyz789", "status": "in_progress" } } }

Workflow 2: Score a Deal and Get Recommendations

Use intelligence tools to score deal health and fetch pricing recommendations.

Score the deal (scope: intelligence:read)
{ "jsonrpc": "2.0", "id": "w2a", "method": "tools/call", "params": { "name": "score_deal", "arguments": { "deal_id": "deal_xyz789" } } }
Get pricing recommendations (scope: intelligence:read)
{ "jsonrpc": "2.0", "id": "w2b", "method": "tools/call", "params": { "name": "get_pricing_recommendations", "arguments": { "deal_id": "deal_xyz789", "strategy": "balanced" } } }
Response excerpt
{ "jsonrpc": "2.0", "id": "w2b", "result": { "content": [{ "type": "text", "text": "{\"score\":82,\"confidence\":\"high\",\"recommendations\":[{\"type\":\"discount\",\"amount\":5,\"rationale\":\"Volume threshold reached\"}]}" }], "isError": false } }

Workflow 3: Negotiate Terms with a Counter-Proposal

Submit a proposal, retrieve the negotiation history, then counter. Requires agent:negotiate scope.

Submit a proposal (scope: agent:negotiate)
{ "jsonrpc": "2.0", "id": "w3a", "method": "tools/call", "params": { "name": "negotiate_terms", "arguments": { "deal_id": "deal_xyz789", "action": "propose", "terms": { "discount_percent": 10, "payment_terms": "net_30" } } } }
Get negotiation history (scope: deals:read)
{ "jsonrpc": "2.0", "id": "w3b", "method": "tools/call", "params": { "name": "get_negotiation_history", "arguments": { "deal_id": "deal_xyz789" } } }
Send counter-proposal (scope: agent:negotiate)
{ "jsonrpc": "2.0", "id": "w3c", "method": "tools/call", "params": { "name": "counter_proposal", "arguments": { "negotiation_id": "neg_abc456", "terms": { "discount_percent": 7, "payment_terms": "net_15" }, "message": "We can offer 7% with net-15 terms." } } }

Workflow 4: Check Delegation Spending Limits

Before executing an expensive action, verify the active delegation has sufficient spending capacity.

Read delegation scope (scope: delegations:read)
{ "jsonrpc": "2.0", "id": "w4a", "method": "tools/call", "params": { "name": "get_delegation_scope", "arguments": { "delegation_id": "del_xxxxx" } } }
Response
{ "jsonrpc": "2.0", "id": "w4a", "result": { "content": [{ "type": "text", "text": "{\"delegation_id\":\"del_xxxxx\",\"scopes\":[\"deals:write\",\"agent:negotiate\"],\"spending_limit\":5000.00,\"spent\":1250.00,\"remaining\":3750.00,\"expires_at\":\"2026-12-31T23:59:59Z\"}" }], "isError": false } }

Workflow 5: Search Across All Entities

Use the global search tool to find customers, products, deals, or contracts by keyword. Requires agent:discover scope.

Global search (scope: agent:discover)
{ "jsonrpc": "2.0", "id": "w5", "method": "tools/call", "params": { "name": "global_search", "arguments": { "query": "enterprise", "types": ["deals", "customers", "products"], "limit": 10 } } }
Response
{ "jsonrpc": "2.0", "id": "w5", "result": { "content": [{ "type": "text", "text": "{\"results\":[{\"type\":\"deal\",\"id\":\"deal_xyz789\",\"label\":\"Enterprise Software Package\",\"score\":0.97},{\"type\":\"product\",\"id\":\"prod_platform_pro\",\"label\":\"Platform Pro (Enterprise)\",\"score\":0.91}],\"total\":12}" }], "isError": false } }

4. Resource Browsing

Resources give agents read access to live tenant data as structured documents. Salesbooth provides static resources (schemas, documentation) and dynamic resources (live deal, product, and customer data).

List all resources — resources/list

Request
{ "jsonrpc": "2.0", "id": "r1", "method": "resources/list", "params": {} }
Response (resource URIs)
{ "jsonrpc": "2.0", "id": "r1", "result": { "resources": [ { "uri": "salesbooth://schemas/deal-terms", "name": "Deal Terms Schema", "mimeType": "application/schema+json" }, { "uri": "salesbooth://schemas/state-machine", "name": "Deal State Machine", "mimeType": "application/json" }, { "uri": "salesbooth://docs/tools", "name": "Agent Tool Reference", "mimeType": "text/plain" }, { "uri": "salesbooth://deals", "name": "Active Deals", "mimeType": "application/json" }, { "uri": "salesbooth://products", "name": "Product Catalog", "mimeType": "application/json" }, { "uri": "salesbooth://customers", "name": "Customer Directory", "mimeType": "application/json" }, { "uri": "salesbooth://widgets", "name": "Widget Configurations", "mimeType": "application/json" }, { "uri": "salesbooth://intelligence/pipeline", "name": "Pipeline Analytics", "mimeType": "application/json" }, { "uri": "salesbooth://delegations", "name": "Agent Delegations", "mimeType": "application/json" }, { "uri": "salesbooth://contracts", "name": "Contracts", "mimeType": "application/json" }, { "uri": "salesbooth://templates", "name": "Deal Templates", "mimeType": "application/json" }, { "uri": "salesbooth://saved-configs", "name": "Saved Configurations", "mimeType": "application/json" }, { "uri": "salesbooth://subscriptions", "name": "Subscriptions", "mimeType": "application/json" }, { "uri": "salesbooth://webhooks", "name": "Webhook Endpoints", "mimeType": "application/json" } ] } }

Read a resource — resources/read

Request
{ "jsonrpc": "2.0", "id": "r2", "method": "resources/read", "params": { "uri": "salesbooth://deals" } }
Response
{ "jsonrpc": "2.0", "id": "r2", "result": { "contents": [{ "uri": "salesbooth://deals", "mimeType": "application/json", "text": "{\"deals\":[{\"id\":\"deal_xyz789\",\"status\":\"in_progress\",\"total_amount\":\"990.00\",\"currency\":\"USD\",\"customer_id\":\"cust_abc123\"}],\"pagination\":{\"total\":42,\"limit\":20,\"offset\":0}}" }] } }

Dynamic resource templates — resources/templates/list

Resource templates allow reading a single entity by ID using parameterized URIs.

Request
{ "jsonrpc": "2.0", "id": "r3", "method": "resources/templates/list", "params": {} }
Response (excerpt)
{ "jsonrpc": "2.0", "id": "r3", "result": { "resourceTemplates": [ { "uriTemplate": "salesbooth://deals/{deal_id}", "name": "Deal by ID", "mimeType": "application/json" }, { "uriTemplate": "salesbooth://products/{product_id}", "name": "Product by ID", "mimeType": "application/json" }, { "uriTemplate": "salesbooth://customers/{customer_id}", "name": "Customer by ID", "mimeType": "application/json" }, { "uriTemplate": "salesbooth://contracts/{contract_id}", "name": "Contract by ID", "mimeType": "application/json" } ] } }
Read a single deal by ID
{ "jsonrpc": "2.0", "id": "r4", "method": "resources/read", "params": { "uri": "salesbooth://deals/deal_xyz789" } }

5. Prompt Templates

Prompt templates are guided multi-step workflows. Agents can inject them as system/user messages to guide an LLM through complex operations without needing to know every individual tool call.

List prompts — prompts/list

Request
{ "jsonrpc": "2.0", "id": "p1", "method": "prompts/list", "params": {} }
Response
{ "jsonrpc": "2.0", "id": "p1", "result": { "prompts": [ { "name": "create-deal", "description": "Guided deal creation workflow: select products, look up or create a customer, configure pricing, and submit the deal." }, { "name": "negotiate-deal", "description": "Structured negotiation workflow: review current deal terms, apply intelligence scoring, propose or counter terms." }, { "name": "configure-widget", "description": "Widget setup workflow: select a site, choose products, configure theme and steps, generate embed code." }, { "name": "review-pipeline", "description": "Pipeline health check: analyze deal distribution by status, identify bottlenecks, get recommended actions." }, { "name": "manage-delegation", "description": "Create or update agent delegations: define scope, spending limits, and expiry for sub-agents." } ] } }

Get a prompt — prompts/get

Request
{ "jsonrpc": "2.0", "id": "p2", "method": "prompts/get", "params": { "name": "negotiate-deal", "arguments": { "deal_id": "deal_xyz789", "strategy": "balanced" } } }
Response
{ "jsonrpc": "2.0", "id": "p2", "result": { "messages": [ { "role": "user", "content": { "type": "text", "text": "You are a deal negotiation agent for Salesbooth. Your task:\n1. Retrieve the current state of deal deal_xyz789 using check_deal_status.\n2. Score the deal using score_deal to understand its health and value.\n3. Review negotiation history via get_negotiation_history.\n4. Apply a balanced strategy: aim for fair value on both sides.\n5. Submit a counter-proposal or accept terms using negotiate_terms / counter_proposal.\nAlways verify scope before acting. Stop if spending limits are exceeded." } } ] } }

6. Error Handling

MCP errors follow the JSON-RPC 2.0 error object format. Tool execution errors are returned as isError: true in the result (not as JSON-RPC errors) so the agent can continue the session.

Error CodeMeaningRecovery
-32600 Invalid Request — missing jsonrpc, method, or invalid envelope structure Check your request body includes "jsonrpc": "2.0" and a valid method string
-32601 Method Not Found — the MCP method name is unknown Verify the method is one of the supported methods listed above. Check spelling.
-32602 Invalid Params — missing required tool parameter or wrong type Call tools/list to inspect the tool’s inputSchema and ensure all required parameters are present
-32603 Internal Error — unexpected server-side error Retry once after a short delay. If persistent, check the sandbox environment or contact support.
Example JSON-RPC error response
{ "jsonrpc": "2.0", "id": "3", "error": { "code": -32602, "message": "Missing required parameter: name" } }
Tool-level error (isError: true in result)
{ "jsonrpc": "2.0", "id": "4", "result": { "content": [{ "type": "text", "text": "{\"error\":true,\"code\":\"insufficient_scope\",\"message\":\"Tool 'create_deal' requires scope 'deals:write'\"}" }], "isError": true } }

7. Scope Requirements by Category

Each MCP tool requires one or more scopes. The base connection itself requires agent:discover. Grant additional scopes by creating an API key with the scopes your agent needs (see Scopes & Permissions).

CategoryRequired Scopes
Deal Managementagent:discover, deals:read, deals:write, agent:execute
Product Catalogproducts:read, products:write
Customer Managementcustomers:read, customers:write
Contractscontracts:read, contracts:write
Negotiationagent:negotiate
Deal Templatesdeals:read, deals:write
Intelligencedeals:read, intelligence:read, intelligence:write
Paymentsdeals:read, deals:write
Subscriptionsdeals:read, deals:write
Widgetsproducts:read, products:write, deals:read, deals:write
Product Configurationproducts:read, products:write
Saved Configurationsdeals:read, deals:write
Webhookswebhooks:read, webhooks:write
Delegationsdelegations:read, delegations:write
Complianceaudit:export, customers:read, customers:write
Searchagent:discover
Auditaudit:read
Sandboxsandbox:read, sandbox:write
Agent Workflowsagent:execute
Agent Trustagent:discover
Cross-Instance Federationagent:discover, agent:negotiate, agent:execute
Agent Registryagent:discover
Deal Participantsdeals:read, deals:write
Deal Closuredeals:read, deals:write, agent:execute
Catalog Managementproducts:write
Documentsdeals:read, deals:write, customers:read
Billingbilling:read

8. Circuit Breaker & Retry Guidance

Tool execution is wrapped in a circuit breaker with a 10-second request timeout and a failure threshold of 5 consecutive failures within 60 seconds. If the circuit is open, the MCP server returns a service_unavailable error with retryable: true in the content.

ParameterValueMeaning
Request timeout10 secondsIndividual tool call must complete within 10 s or it fails
Failure threshold5 failuresCircuit opens after 5 consecutive failures in the window
Failure window60 secondsFailures older than 60 s are no longer counted
Recovery timeout30 secondsCircuit moves to half-open after 30 s; one probe request is allowed
Circuit breaker open — retryable error in tool result
{ "jsonrpc": "2.0", "id": "5", "result": { "content": [{ "type": "text", "text": "{\"error\":true,\"code\":\"service_unavailable\",\"message\":\"Tool execution temporarily unavailable (circuit breaker open). Retry after a short delay.\",\"retryable\":true}" }], "isError": true } }

When retryable is true, wait at least 30 seconds before retrying. Do not flood the endpoint — exponential backoff is recommended. A 503 HTTP response (rather than a JSON-RPC error) means the MCP server itself is unreachable; apply the same backoff strategy.

9. Cross-Instance Federation

The federation tool category implements the salesbooth-negotiate/1.0 protocol, allowing agents to discover offerings on remote Salesbooth instances and execute cross-instance deals without leaving the MCP session.

Discover remote offerings (scope: agent:discover)
{ "jsonrpc": "2.0", "id": "f1", "method": "tools/call", "params": { "name": "discover_federation_partners", "arguments": { "limit": 20 } } }
Initiate a cross-instance negotiation (scope: agent:negotiate)
{ "jsonrpc": "2.0", "id": "f2", "method": "tools/call", "params": { "name": "initiate_federation_negotiation", "arguments": { "remote_instance_url": "https://partner.salesbooth.com", "remote_deal_id": "remote_deal_123", "proposed_terms": { "discount_percent": 5 } } } }

Federation requests are authenticated end-to-end using tenant key pairs and signed JWT assertions. The remote instance validates the incoming salesbooth-negotiate/1.0 request against its federation discovery endpoint (/.well-known/salesbooth-federation) before accepting any proposal.

Cross-Instance Federation

The Federation API enables agents and tenants to discover offerings on remote Salesbooth instances and execute cross-instance deals using the salesbooth-negotiate/1.0 protocol. Federation is generally available — no preview flag is required.

Endpoint: POST /api/v1/federation/negotiate  •  GET /api/v1/federation/negotiate

Required scopes: agent:discover (GET), agent:negotiate (POST)

Authentication: Requests are signed end-to-end with tenant Ed25519 key pairs. Remote instances validate incoming envelopes against the originator’s DID document at /.well-known/salesbooth-federation.

Actions (POST)

ActionDescription
discoverCross-instance product and deal discovery — find offerings available on a remote instance
sendSend a signed negotiation envelope to a remote instance to initiate a deal
negotiateReceive and process an incoming negotiation envelope from a remote instance
escrowCoordinate matched escrow creation across both instances simultaneously
settleInitiate 2-phase escrow settlement (PREPARE → COMMIT or ROLLBACK)
disputeInitiate escrow dispute — freezes funds on both sides and fires escrow.* webhooks

GET Actions

?action=Description
status (default)Return this instance’s federation capabilities manifest (protocol version, supported actions, public key)
auditRetrieve the federation audit trail for a cross-instance transaction by ?xref_id=
Get federation status
curl https://salesbooth.com/api/v1/federation/negotiate \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Discover remote offerings
curl -X POST https://salesbooth.com/api/v1/federation/negotiate \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "discover", "remote_url": "https://partner.salesbooth.com", "query": { "category": "software", "currency": "USD" } }'
Send a negotiation envelope
curl -X POST https://salesbooth.com/api/v1/federation/negotiate \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "send", "remote_url": "https://partner.salesbooth.com", "envelope": { "deal_id": "deal_remote_123", "proposed_terms": { "discount_percent": 10, "currency": "USD" }, "expires_at": "2026-03-13T12:00:00Z" } }'
GET /api/v1/federation/negotiate
Return this instance’s federation capabilities manifest or retrieve the audit trail for a specific cross-instance transaction. Requires agent:discover scope.
ParameterTypeDescription
actionstringstatus (default) for capabilities manifest; audit to retrieve a transaction audit trail
xref_idstringCross-reference transaction ID — required when action=audit
Example — get federation status
curl https://salesbooth.com/api/v1/federation/negotiate \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Example — retrieve audit trail
curl "https://salesbooth.com/api/v1/federation/negotiate?action=audit&xref_id=xref_abc123" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/federation/negotiate
Process a cross-instance negotiation action: discover remote offerings, send or receive negotiation envelopes, coordinate escrow, settle, or raise disputes. Requires agent:negotiate scope.
FieldTypeDescription
action requiredstringdiscover, send, negotiate, escrow, settle, or dispute
remote_urlstringBase URL of the remote Salesbooth instance (required for discover and send)
envelopeobjectSigned negotiation envelope (required for send and negotiate)
queryobjectDiscovery query filters (used with action=discover): category, currency, etc.
Example — discover remote offerings
curl -X POST https://salesbooth.com/api/v1/federation/negotiate \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "discover", "remote_url": "https://partner.salesbooth.com", "query": { "category": "software", "currency": "USD" } }'

Instance Discovery

Remote instances advertise their federation support via a well-known endpoint. This is used during the handshake to verify the remote tenant’s public key and supported protocol versions.

Well-known discovery endpoint
GET /.well-known/salesbooth-federation
GET /api/v1/federation/discovery?tenant_id={tenant_id}
Return the federation discovery manifest for a specific tenant. Public endpoint — no authentication required. Remote instances call this to retrieve the tenant’s federation capabilities, supported protocol versions, and public Ed25519 key before initiating a cross-instance negotiation.
ParameterTypeDescription
tenant_id requiredstringTenant whose federation manifest to retrieve
Example
curl "https://salesbooth.com/api/v1/federation/discovery?tenant_id=tenant_xxxxx"
Response
{ "error": false, "success": true, "data": { "manifest": { "version": "1.0", "tenant_id": "tenant_xxxxx", "endpoints": { "negotiate": "https://salesbooth.com/api/v1/federation/negotiate", "did_document": "https://salesbooth.com/api/v1/did-document" }, "capabilities": ["negotiate", "escrow", "settle", "dispute"], "protocol_versions": ["salesbooth-negotiate/1.0"] } } }
GET /api/v1/tenant/public-key?tenant_id={tenant_id}
Get a tenant’s Ed25519 public key. Public endpoint — no authentication required. Used by third parties and remote instances to fetch a tenant’s signing key for independent verification of deal signatures without trusting Salesbooth infrastructure. Returns the key in raw (base64), PEM, and JWK formats by default.
ParameterTypeDescription
tenant_idstringTenant whose public key to retrieve (required if key_id not provided). Pass _current to resolve from session.
key_idstringRetrieve a specific signing key by ID (useful when verifying a signature that references a rotated key)
formatstringKey format: raw, pem, jwk, or all (default)
include_rotatedflagReturn all keys including rotated ones (omit for active key only)
Example
curl "https://salesbooth.com/api/v1/tenant/public-key?tenant_id=tenant_xxxxx"
Response
{ "error": false, "data": { "tenant_id": "tenant_xxxxx", "key_id": "key_abc123", "algorithm": "ed25519", "key_version": 1, "status": "active", "created_at": "2026-01-15T08:00:00Z", "public_key": "MCowBQYDK2VwAyEA...", "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA...\n-----END PUBLIC KEY-----", "public_key_jwk": { "kty": "OKP", "crv": "Ed25519", "kid": "key_abc123", "x": "..." } } }

Trust requirement: Agents must be at Trust Level 3 (Trusted) to access federation capabilities. Cross-instance negotiation envelopes include a verifiable credential attesting to the originating agent’s trust level, which the remote instance validates before accepting any proposal.

DID Document

Every Salesbooth tenant publishes a W3C Decentralized Identifier (DID) document that remote instances use to verify deal signatures and federation credentials without trusting Salesbooth infrastructure.

GET /api/v1/did-document?tenant_id={tenant_id}
Return the W3C DID document for a tenant. Public endpoint — no authentication required. Includes the tenant’s Ed25519 verification method and service endpoints for federation, deal verification, and key rotation.
ParameterTypeDescription
tenant_idstringTenant whose DID document to retrieve. Omit to retrieve the document for the authenticated tenant.
Example
curl "https://salesbooth.com/api/v1/did-document?tenant_id=tenant_xxxxx"
Response
{ "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:web:salesbooth.com:tenant_xxxxx", "verificationMethod": [ { "id": "did:web:salesbooth.com:tenant_xxxxx#key-1", "type": "Ed25519VerificationKey2020", "controller": "did:web:salesbooth.com:tenant_xxxxx", "publicKeyMultibase": "z..." } ], "authentication": ["did:web:salesbooth.com:tenant_xxxxx#key-1"], "service": [ { "id": "did:web:salesbooth.com:tenant_xxxxx#federation", "type": "SalesboothFederation", "serviceEndpoint": "https://salesbooth.com/api/v1/federation/negotiate" } ] }

Federation Peers

Manage the list of trusted remote Salesbooth instances your tenant federates with. Peers are used by the federation engine to pre-authorise cross-instance deal discovery and negotiation without requiring per-request trust verification. Requires agent:execute scope.

GET /api/v1/federation-peers
List all federation peers for the tenant. Requires agent:discover scope.
Example
curl https://salesbooth.com/api/v1/federation-peers \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "peers": [ { "id": 1, "hostname": "partner.salesbooth.com", "remote_tenant_id": "tenant_yyyyy", "trust_level": 3, "status": "active", "created_at": "2026-01-15T10:00:00Z" } ], "count": 1, "open_mode": false } }
POST /api/v1/federation-peers
Register a new federation peer. Requires agent:execute scope.
FieldTypeDescription
hostname requiredstringHostname of the remote Salesbooth instance (e.g. partner.salesbooth.com)
remote_tenant_idstringTenant ID on the remote instance to federate with specifically
trust_levelintegerInitial trust level for this peer (0–5, default: 1)
statusstringactive or suspended (default: active)
Example
curl -X POST https://salesbooth.com/api/v1/federation-peers \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "hostname": "partner.salesbooth.com", "remote_tenant_id": "tenant_yyyyy", "trust_level": 3 }'
Response (201)
{ "error": false, "data": { "id": 1, "hostname": "partner.salesbooth.com", "remote_tenant_id": "tenant_yyyyy", "trust_level": 3, "status": "active" } }
PATCH /api/v1/federation-peers?id={peer_id}
Update a federation peer’s trust level or status. Requires agent:execute scope.
FieldTypeDescription
statusstringactive or suspended
trust_levelintegerNew trust level (0–5)
Example
curl -X PATCH "https://salesbooth.com/api/v1/federation-peers?id=1" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "status": "suspended" }'
Response
{ "error": false, "data": { "updated": true, "id": 1 } }
DELETE /api/v1/federation-peers?id={peer_id}
Remove a federation peer. Cross-instance negotiations with this peer will no longer be pre-authorised. Requires agent:execute scope.
Example
curl -X DELETE "https://salesbooth.com/api/v1/federation-peers?id=1" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "deleted": true, "id": 1 } }

API Keys

Create and manage API keys for your integration. Keys carry scopes that restrict which operations they can perform. This endpoint requires session (cookie) authentication — API keys cannot be used to manage other API keys.

Session authentication required. All /api/v1/keys endpoints require an active dashboard session. You cannot use an API key to create or revoke other API keys.

GET /api/v1/keys
List all API keys for your tenant. Secret values are masked after initial creation.
Response
{ "error": false, "data": [ { "id": "key_xxxxx", "name": "Production Integration", "prefix": "sb_live_", "scopes": ["deals:read", "customers:read"], "created_at": "2026-01-15T10:00:00Z", "last_used_at": "2026-03-10T08:30:00Z" } ] }
POST /api/v1/keys
Create a new API key. The full secret is only returned once at creation time — store it securely.
FieldTypeDescription
name requiredstringDescriptive name for the key
scopesarrayArray of scope strings (see Scopes & Permissions). Defaults to full access (["*"]) if omitted.
environmentstringlive or test (default: live)
expires_atstringISO 8601 expiry datetime (optional)
Example
curl -X POST https://salesbooth.com/api/v1/keys \ -H "Cookie: session=..." \ -H "Content-Type: application/json" \ -d '{ "name": "CI/CD Pipeline", "scopes": ["deals:read", "customers:write"], "environment": "test" }'
Response (201)
{ "error": false, "data": { "id": "key_xxxxx", "secret": "sb_test_xxxxxxxxxxxxxxxxxxxxxxxx", "name": "CI/CD Pipeline", "scopes": ["deals:read", "customers:write"] } }
PATCH /api/v1/keys?id={key_id}
Update an API key’s name, scopes, or expiry date.
Example
curl -X PATCH "https://salesbooth.com/api/v1/keys?id=key_xxxxx" \ -H "Cookie: session=..." \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Key", "scopes": ["deals:read", "deals:write"] }'
DELETE /api/v1/keys?id={key_id}
Revoke an API key immediately. All requests using this key will be rejected with 401 INVALID_KEY.
Example
curl -X DELETE "https://salesbooth.com/api/v1/keys?id=key_xxxxx" \ -H "Cookie: session=..."

Sandbox

Test your integration without affecting live data. Sandbox endpoints require a test API key (sb_test_*) or sandbox mode enabled in the dashboard. All sandbox data is isolated from production.

Test keys only. All sandbox endpoints return 403 SANDBOX_ONLY when called with a live API key (sb_live_*). Generate a test key from the API Keys page in your dashboard.

POST /api/v1/sandbox/reset
Clear all test data for your tenant. Deletes test deals, customers, products, contracts, and escrow records in dependency-safe order. Live data is never affected.
Example
curl -X POST https://salesbooth.com/api/v1/sandbox/reset \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "action": "reset", "environment": "test", "sandbox": true, "deleted": { "deals": 10, "customers": 5, "products": 10, "contracts": 1 }, "total_deleted": 26, "message": "Cleared 26 test records across 4 tables." } }
POST /api/v1/sandbox/seed
Populate your sandbox with representative test data. Creates 5 customers, 10 products (subscriptions and one-time), 10 deals across all pipeline stages (draft, in_progress, pending_signature, pending_payment, closed, cancelled), deal line items, and 1 contract.
Example
curl -X POST https://salesbooth.com/api/v1/sandbox/seed \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response (201)
{ "error": false, "data": { "action": "seed", "environment": "test", "sandbox": true, "seeded": { "customers": 5, "products": 10, "deals": 10, "deal_line_items": 22, "contracts": 1 }, "total_seeded": 48, "message": "Created 48 test records: 5 customers, 10 products, 10 deals, 22 line items, 1 contracts." } }
POST /api/v1/sandbox/simulate_webhook
Trigger a webhook event with a synthetic payload. The event is dispatched through the normal webhook system to all active webhooks subscribed to the specified event type. Use this to test your webhook handlers without creating real data.
FieldDescription
event requiredEvent type to simulate (e.g. deal.created, deal.closed, payment.received)
dataCustom payload object. If omitted, a realistic synthetic payload is generated automatically.
Example
curl -X POST https://salesbooth.com/api/v1/sandbox/simulate_webhook \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "event": "deal.closed", "data": { "deal_id": "deal_test_abc123", "total": "2500.00", "currency": "USD" } }'
Response
{ "error": false, "data": { "action": "simulate_webhook", "environment": "test", "sandbox": true, "event": "deal.closed", "deliveries": 2, "webhook_ids": ["wh_xxxxx", "wh_yyyyy"], "message": "Dispatched 'deal.closed' event to 2 webhook(s)." } }
GET /api/v1/sandbox/status
Check the current state of your sandbox environment. Returns counts of test data across all entity types.
Example
curl https://salesbooth.com/api/v1/sandbox/status \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "environment": "test", "sandbox": true, "counts": { "deals": 10, "customers": 5, "products": 10, "contracts": 1, "deal_escrow": 0 }, "total_test_records": 26 } }

Playground API

The Playground API provisions ephemeral sandbox keys for the interactive API playground. Keys are auto-generated with limited scopes and expire after 2 hours. No authentication required — playground sessions are inherently sandboxed. Rate limited to 10 sessions per hour per IP.

POST /api/v1/playground/session
Create an ephemeral playground session. Returns a temporary sb_test_* API key with sandbox scopes that expires in 2 hours. Sandbox data is automatically seeded on first use. No authentication required.
Example
curl -X POST https://salesbooth.com/api/v1/playground/session \ -H "Content-Type: application/json"
Response (200)
{ "error": false, "data": { "api_key": "sb_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "key_prefix": "sb_test_xxxx", "expires_at": "2026-03-24T12:00:00Z", "expires_in": 7200, "environment": "test", "sandbox": true, "scopes": ["deals:read", "deals:write", "customers:read", "customers:write", "products:read", "contracts:read", "webhooks:read", "sandbox:read", "sandbox:write"], "seeded": true } }
GET /api/v1/playground/session
Check whether a playground session key is still valid. Pass the key prefix to look up its expiry status. No authentication required.
ParameterTypeDescription
key_prefix requiredstringFirst 12 characters of the playground API key (min 8 chars)
Example
curl "https://salesbooth.com/api/v1/playground/session?key_prefix=sb_test_xxxx"
Response (200)
{ "error": false, "data": { "valid": true, "expires_at": "2026-03-24T12:00:00Z", "reason": null } }

Widgets

Manage embedded deal widgets programmatically. Widgets are configured per-site with auto-generated publishable API keys and can be created manually or from deal templates.

GET /api/v1/widget-config
List all widget configurations for the authenticated tenant, or retrieve a specific widget by ID. Also supports public access via a publishable API key — no authentication required when using api_key.
ParameterDescription
idWidget ID to retrieve a specific widget. When omitted, returns the full list for the authenticated tenant.
api_keyPublishable API key (sb_pub_*) for public widget config access. No authentication required when using this parameter — this is the primary mechanism for embedded widgets to fetch their configuration client-side.
Example (authenticated list)
curl https://salesbooth.com/api/v1/widget-config \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Example (public access via publishable key)
curl "https://salesbooth.com/api/v1/widget-config?api_key=sb_pub_xxxxxxxxxxxx"
Response (public access)
{ "error": false, "data": { "widget_id": "wc_xxxxxxxxxxxx", "title": "Get Started", "theme_color": "#2563eb", "currency": "USD", "merchant_available": true, "stripe_publishable_key": "pk_live_xxxxxxxxxxxx", "products": ["prod_xxxxxxxxxxxx"], "steps": ["products", "customer", "payment"] } }
GET /api/v1/widget-config?id={widget_id}
Retrieve a specific widget configuration by ID (authenticated).
ParameterDescription
id requiredWidget ID to retrieve
api_keyPublishable API key (sb_pub_*) — use instead of Authorization header for public/client-side access
Example
curl "https://salesbooth.com/api/v1/widget-config?id=wc_xxxxxxxxxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "widget_id": "wc_xxxxxxxxxxxx", "site_id": "site_xxxxxxxxxxxx", "title": "Get Started", "theme_color": "#2563eb", "currency": "USD", "products": ["prod_xxxxxxxxxxxx"], "steps": ["products", "customer", "payment"], "api_key": "sb_pub_xxxxxxxxxxxx", "created_at": "2024-01-15T10:00:00Z", "updated_at": "2024-01-15T10:00:00Z" } }
POST /api/v1/widget-config
Create a new widget configuration. Auto-generates a publishable API key scoped to the site’s domain.
FieldDescription
site_id requiredThe site to attach the widget to
titleWidget title (default: “Create a Deal”)
theme_colorHex colour code (default: #2563eb)
currencyISO currency code (default: USD)
productsComma-separated product IDs
PATCH /api/v1/widget-config?id={widget_id}
Partially update a widget configuration. Only provided fields are changed.
FieldDescription
titleWidget title
theme_colorHex colour code
currencyISO currency code
productsComma-separated product IDs
cta_textCall-to-action button label
enable_negotiationBoolean — enable buyer negotiation
localeBCP 47 locale code (e.g. en-AU)
dark_modeBoolean — enable dark theme
custom_cssCustom CSS string injected into the widget
Example
curl -X PATCH "https://salesbooth.com/api/v1/widget-config?id=wgt_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "theme_color": "#10b981", "cta_text": "Get a Quote", "enable_negotiation": true }'
DELETE /api/v1/widget-config?id={widget_id}
Delete a widget configuration and revoke its publishable API key. The embed code will stop working immediately.
Example
curl -X DELETE "https://salesbooth.com/api/v1/widget-config?id=wgt_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/widget-config/from-template
Generate a pre-filled widget configuration from a deal template. Reads the template’s product list and runs auto-configure logic. Does not save — returns suggestions for the widget form to pre-fill.
FieldDescription
template_id requiredDeal template identifier (e.g. dtpl_xxxxx)
site_idSite to associate with the generated config
Example
curl -X POST https://salesbooth.com/api/v1/widget-config/from-template \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "template_id": "dtpl_abc123", "site_id": "site_xyz" }'
Response
{ "error": false, "success": true, "data": { "title": "Enterprise Starter Pack", "products": "prod_1, prod_2", "currency": "USD", "deal_template_id": "dtpl_abc123", "theme_color": "#2563eb", "cta_text": "Get Started" } }
POST /api/v1/widget-config/auto-configure
Generate a suggested widget configuration from a list of product IDs. Analyses the products and suggests optimal widget settings including locale, currency, step order, and feature flags. Does not save — returns a configuration object for review before creating.
FieldTypeDescription
product_ids requiredarrayArray of product ID strings to base the configuration on
Example
curl -X POST "https://salesbooth.com/api/v1/widget-config/auto-configure" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "product_ids": ["prod_aaa", "prod_bbb"] }'
Response
{ "error": false, "data": { "products": "prod_aaa, prod_bbb", "currency": "USD", "locale": "en", "theme_color": "#2563eb", "show_negotiation": true, "show_contract": false } }
GET /api/v1/widget-config/embed-code
Get a ready-to-paste HTML embed snippet for a widget, including the <script> tag with SRI integrity attributes and the <salesbooth-deal> custom element. Also accessible as GET /api/v1/widget-config?id={id}&action=embed-code.
ParameterDescription
id requiredWidget identifier
Example
curl "https://salesbooth.com/api/v1/widget-config/embed-code?id=wgt_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "html": "<!-- Salesbooth Deal Widget -->\n<script src=\"...\" integrity=\"sha384-...\" crossorigin=\"anonymous\"></script>\n<salesbooth-deal api-key=\"sb_pub_xxxxx\"></salesbooth-deal>", "integrity": "sha384-...", "sdk_url": "https://salesbooth.com/sdk/v1/salesbooth-widget.js" } }

SDK Usage

const sb = new Salesbooth({ apiKey: 'sb_test_example_key_do_not_use' }); // List all widgets const { widgets } = await sb.widgets.list(); // Create a widget from a deal template const config = await sb.widgets.createFromTemplate('dtpl_abc123', 'site_xyz', { theme_color: '#10b981' }); // Get the embed code for a widget const { html } = await sb.widgets.getEmbedCode('wgt_xxxxx'); document.getElementById('widget-container').innerHTML = html;

Saved Configurations

Save product configuration snapshots with shareable short codes. Buyers can build a configuration in the widget, save it, share it via URL, and later convert it into a deal. Authenticated with a publishable key (sb_pub_*) via Bearer header.

Rate limits. Saves are limited to 10 per hour per IP. Reads are limited to 30 per minute per IP. Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are included in every response.

Short Codes

Each saved configuration receives a unique short code — an 8–16 character hex string (e.g. a3f8b21c). Short codes are used to retrieve and share configurations via URLs like https://salesbooth.com/configure/a3f8b21c.

Configurations expire after 30 days by default (configurable via expires_in, 1–365 days). Widget-level TTL defaults can be set in the widget configuration.

POST /api/v1/saved-configs
Save a product configuration snapshot. Returns a short code and shareable URL.
FieldDescription
product_selections requiredArray of product selections with product_id, name, quantity, and configured_price
pricing_snapshot requiredPricing breakdown object (subtotals, discounts, taxes at time of configuration)
option_selectionsObject mapping product IDs to their selected option values
subtotalTotal price as a number
currencyISO 4217 currency code (default: USD)
customer_nameBuyer name (optional)
customer_emailBuyer email (optional)
expires_inExpiration in days, 1–365 (default: 30)
Example
curl -X POST https://salesbooth.com/api/v1/saved-configs \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "product_selections": [ { "product_id": "prod_abc123", "name": "Pro Plan", "quantity": 1, "configured_price": 99.00 } ], "pricing_snapshot": { "subtotal": 99.00, "tax": 8.17, "total": 107.17 }, "subtotal": 99.00, "currency": "USD", "customer_email": "buyer@example.com", "expires_in": 14 }'
Response (201)
{ "error": false, "success": true, "data": { "short_code": "a3f8b21c", "share_url": "https://salesbooth.com/configure/a3f8b21c", "expires_at": "2026-03-22 14:30:00", "created_at": "2026-03-08 14:30:00" } }
GET /api/v1/saved-configs?code={short_code}
Retrieve a saved configuration by its short code. Includes price change detection — if product prices have changed since the configuration was saved, the price_changes array will list the differences.
ParameterDescription
code requiredThe 8–16 character hex short code
Example
curl https://salesbooth.com/api/v1/saved-configs?code=a3f8b21c \ -H "Authorization: Bearer sb_pub_xxxxx"
Response
{ "error": false, "success": true, "data": { "short_code": "a3f8b21c", "widget_id": "wgt_xxxxx", "product_selections": [...], "pricing_snapshot": {...}, "subtotal": 99.00, "currency": "USD", "expired": false, "expires_at": "2026-03-22 14:30:00", "share_url": "https://salesbooth.com/configure/a3f8b21c", "price_changes": [] } }
PATCH /api/v1/saved-configs?id={short_code}
Update mutable fields of a saved configuration. Authenticated with a publishable API key (sb_pub_*).
FieldDescription
customer_nameBuyer name
customer_emailBuyer email address
option_selectionsObject mapping product IDs to their selected option values
Example
curl -X PATCH "https://salesbooth.com/api/v1/saved-configs?id=a3f8b21c" \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "customer_name": "Jane Smith", "customer_email": "jane@example.com" }'
DELETE /api/v1/saved-configs?id={short_code}
Permanently delete a saved configuration by its short code. Authenticated with a publishable API key (sb_pub_*).
Example
curl -X DELETE "https://salesbooth.com/api/v1/saved-configs?id=a3f8b21c" \ -H "Authorization: Bearer sb_pub_xxxxx"
POST /api/v1/saved-configs?action=to_deal
Convert a saved configuration into a deal. Creates a customer record, a draft deal with line items, and applies any discounts from the pricing snapshot. Returns 409 if already converted, 410 if expired.
FieldDescription
short_code requiredThe short code of the saved configuration
customer_name requiredBuyer name (overrides saved value if provided)
customer_email requiredBuyer email (overrides saved value if provided)
customer_phoneBuyer phone number
Example
curl -X POST https://salesbooth.com/api/v1/saved-configs?action=to_deal \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "short_code": "a3f8b21c", "customer_name": "Jane Smith", "customer_email": "jane@example.com" }'
Response (201)
{ "error": false, "success": true, "data": { "deal_id": "deal_xxxxx", "deal": { ... }, "converted_from": "a3f8b21c" } }

Widget Analytics

Track widget conversion funnels and user engagement. Record events from embedded widgets and retrieve aggregated metrics.

POST /api/v1/widget-analytics
Record a widget analytics event (view, step completion, conversion, etc.).
FieldTypeDescription
api_key requiredstringWidget publishable API key
session_id requiredstringUnique session identifier
event_type requiredstringEvent type: view, step, submit, error
stepstringCurrent step name
dataobjectAdditional event data
Example
curl -X POST https://salesbooth.com/api/v1/widget-analytics \ -H "Content-Type: application/json" \ -d '{ "api_key": "sb_pub_xxxxx", "session_id": "sess_abc123", "event_type": "step", "step": "product_selection" }'
GET /api/v1/widget-analytics?widget_id={widget_id}
Retrieve aggregated analytics for a widget — views, conversion rates, and funnel drop-off.
ParameterTypeDescription
widget_id requiredstringWidget identifier
daysintegerLookback period in days (default: 30)
Example
curl https://salesbooth.com/api/v1/widget-analytics?widget_id=wgt_xxxxx&days=7 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Uploads

Upload image files for products, option swatches, and other assets.

POST /api/v1/uploads
Upload an image file. Accepts JPEG, PNG, GIF, and WebP formats. Max file size: 2 MB.
Example
curl -X POST https://salesbooth.com/api/v1/uploads \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -F "file=@product-image.jpg"
Response (201)
{ "error": false, "data": { "url": "https://salesbooth.com/uploads/img_abc123.jpg", "filename": "product-image.jpg", "size": 145280, "mime_type": "image/jpeg" } }

Credits

Prepaid credit balance management. Check balance, top up via Stripe Checkout, view ledger history, and estimate deal costs.

GET /api/v1/credits
Get current credit balance.
Example
curl https://salesbooth.com/api/v1/credits \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "balance": 5000, "currency": "credits" } }
GET /api/v1/credits?action=ledger
Get credit ledger history showing all credit and debit transactions.
ParameterTypeDescription
limitintegerMax results (default: 50)
offsetintegerPagination offset
typestringFilter: credit or debit
Example
curl https://salesbooth.com/api/v1/credits?action=ledger&limit=10 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/credits?action=topup
Create a Stripe Checkout session to top up credits.
FieldTypeDescription
amount requirednumberNumber of credits to purchase
success_urlstringRedirect URL on success
cancel_urlstringRedirect URL on cancel
Example
curl -X POST https://salesbooth.com/api/v1/credits?action=topup \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "amount": 1000 }'
POST /api/v1/credits?action=estimate
Estimate the credit cost for a deal before committing.
FieldTypeDescription
deal_idstringDeal to estimate cost for
Example
curl -X POST https://salesbooth.com/api/v1/credits?action=estimate \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123" }'

Billing

Billing dashboard endpoints for credit balance, auto top-up configuration, usage charts, and alert settings.

GET /api/v1/billing
Get billing dashboard data including balance, usage summary, and auto top-up status.
Example
curl https://salesbooth.com/api/v1/billing \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/billing?action=usage-daily
Get daily usage data for charts and trend analysis.
ParameterTypeDescription
daysintegerLookback period in days (default: 30)
Example
curl https://salesbooth.com/api/v1/billing?action=usage-daily&days=14 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/billing?action=auto-topup
Configure automatic credit top-up when balance falls below a threshold.
FieldTypeDescription
enabled requiredbooleanEnable or disable auto top-up
thresholdintegerTrigger when balance drops below this
amountintegerCredits to purchase on trigger
Example
curl -X POST https://salesbooth.com/api/v1/billing?action=auto-topup \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "threshold": 100, "amount": 500 }'
POST /api/v1/billing?action=alert-settings
Configure low-balance alert notifications.
Example
curl -X POST https://salesbooth.com/api/v1/billing?action=alert-settings \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "low_balance_threshold": 50, "notify_email": true }'

Team

Manage team members and roles. Invite users, update roles, and remove team members.

GET /api/v1/team
List all team members with their roles and invitation status.
Example
curl https://salesbooth.com/api/v1/team \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/team
Invite a new team member via email.
FieldTypeDescription
email requiredstringEmail address to invite
role requiredstringadmin, member, or viewer
Example
curl -X POST https://salesbooth.com/api/v1/team \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "email": "colleague@example.com", "role": "member" }'
PATCH /api/v1/team
Update a team member’s role.
FieldTypeDescription
membership_id requiredintegerTeam membership identifier
role requiredstringNew role: admin, member, or viewer
Example
curl -X PATCH https://salesbooth.com/api/v1/team \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "membership_id": "tm_xxxxx", "role": "admin" }'
DELETE /api/v1/team?id={membership_id}
Remove a team member.
Example
curl -X DELETE "https://salesbooth.com/api/v1/team?id=tm_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Trust Levels

View your tenant’s trust status, progress metrics, auto top-up ceilings, and level change history.

GET /api/v1/trust
Get the current tenant trust level, score, and progression details.
Example
curl https://salesbooth.com/api/v1/trust \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": { "level": "established", "score": 85, "auto_topup_ceiling": 10000, "next_level": "premium", "next_level_score": 90 } }
GET /api/v1/trust?action=history
Get the history of trust level changes for the tenant.
ParameterTypeDescription
limitintegerMax results (default: 50)
offsetintegerPagination offset
Example
curl https://salesbooth.com/api/v1/trust?action=history \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/trust/revocations
Retrieve the list of revoked agent credentials and trust demotions. Public endpoint — no authentication required. Remote instances call this during federation to verify that incoming credentials have not been revoked since issuance.
Example
curl "https://salesbooth.com/api/v1/trust/revocations"
Response
{ "error": false, "data": { "revocations": [ { "credential_id": "cred_abc123", "revoked_at": "2026-02-10T08:00:00Z", "reason": "trust_demotion" } ], "updated_at": "2026-03-18T12:00:00Z" } }

Sites

Create and manage tenant websites. Each site can have multiple pages and AI-generated content. Sites are used for deal landing pages, product showcases, and customer portals.

GET /api/v1/sites
List all sites for the tenant, or retrieve a specific site by ID.
ParameterTypeDescription
idstringRetrieve a specific site
Example
curl https://salesbooth.com/api/v1/sites \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/sites
Create a new site.
FieldTypeDescription
domain requiredstringDomain for the site (subdomain or custom domain)
namestringSite display name
statusstringactive, inactive, or coming_soon
settingsobjectOptional site settings object
Example
curl -X POST https://salesbooth.com/api/v1/sites \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Enterprise Portal", "domain": "acme.salesbooth.com", "status": "coming_soon" }'
PATCH /api/v1/sites?id={site_id}
Update site settings, status, or domain configuration.
Example
curl -X PATCH "https://salesbooth.com/api/v1/sites?id=site_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "status": "active" }'
DELETE /api/v1/sites?id={site_id}
Delete a site and all its pages.
Example
curl -X DELETE "https://salesbooth.com/api/v1/sites?id=site_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Site Pages

Create and manage individual pages within a site. Pages contain HTML content generated by AI or edited manually.

GET /api/v1/site-pages
List all pages for a site, or retrieve a specific page.
ParameterTypeDescription
idstringRetrieve a specific page
site_idstringFilter pages by site
Example
curl "https://salesbooth.com/api/v1/site-pages?site_id=site_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/site-pages
Create a new page within a site.
FieldTypeDescription
site_id requiredstringThe parent site
title requiredstringPage title
slugstringURL slug (auto-generated from title if omitted)
contentstringPage HTML content
statusstringdraft or published
Example
curl -X POST https://salesbooth.com/api/v1/site-pages \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "site_id": "site_xxxxx", "title": "Enterprise Pricing", "slug": "pricing", "status": "published" }'
PATCH /api/v1/site-pages?id={page_id}
Update a page’s content, title, or status.
Example
curl -X PATCH "https://salesbooth.com/api/v1/site-pages?id=page_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "status": "published", "title": "Updated Pricing Page" }'
DELETE /api/v1/site-pages?id={page_id}
Delete a site page.
Example
curl -X DELETE "https://salesbooth.com/api/v1/site-pages?id=page_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Site Suggestions

AI-driven optimization recommendations for your sites. The system analyzes session replays and conversion data to generate actionable suggestions. Accept or reject suggestions to apply or dismiss them, with rollback support.

GET /api/v1/site-suggestions
List optimization suggestions, or retrieve a specific suggestion. Pass insights=1 for acceptance rates and impact benchmarks, or health_score=1&site_id=x for a site’s optimization health score.
ParameterTypeDescription
idstringRetrieve a specific suggestion
site_idstringFilter by site
statusstringFilter: pending, accepted, rejected
insightsstringSet to 1 to get learning insights (acceptance rates, impact benchmarks)
Example
curl "https://salesbooth.com/api/v1/site-suggestions?site_id=site_xxxxx&status=pending" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
PATCH /api/v1/site-suggestions?id={suggestion_id}
Accept, reject, or rollback an optimization suggestion.
FieldTypeDescription
action requiredstringaccept, reject, or rollback
Example — Accept a suggestion
curl -X PATCH "https://salesbooth.com/api/v1/site-suggestions?id=sugg_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "accept" }'
POST /api/v1/site-suggestions
Batch accept or reject suggestions, update optimizer settings, trigger analysis, or export suggestions.
FieldTypeDescription
action requiredstringbatch, settings, analyze, export, or ab_test
suggestion_idsarrayFor batch: array of suggestion IDs
batch_actionstringFor batch: accept or reject
Example — Batch accept
curl -X POST https://salesbooth.com/api/v1/site-suggestions \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "action": "batch", "suggestion_ids": ["sugg_aaa", "sugg_bbb"], "batch_action": "accept" }'

Plugins

Browse the plugin marketplace and manage installed plugins. Plugins extend platform functionality with features like analytics, website builder, channel integrations, and more.

GET /api/v1/plugins
List available plugins in the marketplace, or list installed plugins for the tenant.
ParameterTypeDescription
installedbooleanSet to 1 to list only installed plugins
Example
curl https://salesbooth.com/api/v1/plugins?installed=1 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "data": [ { "id": "analytics", "name": "Analytics", "description": "Session replays, conversion funnels, and heatmaps", "installed": true, "version": "1.2.0" } ] }
POST /api/v1/plugins
Install a plugin for the current tenant.
FieldTypeDescription
plugin_id requiredstringPlugin identifier from the marketplace listing
Example
curl -X POST https://salesbooth.com/api/v1/plugins \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "plugin_id": "analytics" }'
DELETE /api/v1/plugins?id={plugin_id}
Uninstall a plugin from the current tenant.
Example
curl -X DELETE "https://salesbooth.com/api/v1/plugins?id=analytics" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

GDPR Compliance

Endpoints for GDPR data subject rights: right of access (Art. 15), data portability (Art. 20), right to erasure (Art. 17), consent management, and compliance monitoring. All actions are logged in the audit trail.

Anonymisation, not deletion. Financial records (deals, contracts, payments) are preserved for legal and accounting requirements but anonymised with a REDACTED-{hash} scheme. Customer PII is fully erased. The audit trail records every erasure action for compliance verification.

Required Scopes

customers:readRequired for data export, consent retrieval, erasure verification, dashboard, and processing register
customers:writeRequired for erasure, consent recording, consent withdrawal, and retention policy updates

Data Subject Rights

Endpoints supporting data subject access requests (DSARs) and the right to be forgotten.

GET /api/v1/gdpr/export
Export all data held about a customer (Art. 15 Right of Access / Art. 20 Data Portability). Returns customer profile, deals, contracts, consent records, communications, and audit trail in a portable JSON format.
ParameterTypeDescription
customer_id requiredstringThe customer identifier
Example
curl "https://salesbooth.com/api/v1/gdpr/export?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
DELETE /api/v1/gdpr/erase
Erase customer personal data within the local system (Art. 17 Right to Erasure). PII is removed from the customer record. Financial records in deals and contracts are anonymised with REDACTED-{hash} to preserve accounting integrity. Does not propagate to external systems — use /gdpr/full_erase for cross-system erasure.
ParameterTypeDescription
customer_id requiredstringThe customer identifier
Body FieldTypeDescription
reasonstringReason for erasure (logged in audit trail, default: “GDPR erasure request”)
Example
curl -X DELETE "https://salesbooth.com/api/v1/gdpr/erase?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "Customer requested data deletion"}'
DELETE /api/v1/gdpr/full_erase
Full cross-system GDPR erasure (Art. 17 Right to be Forgotten). Atomically erases all customer PII across all systems: customer record, deals, contracts, communication logs, audit trail, consent records, webhook payloads, and search indexes.
ParameterTypeDescription
customer_id requiredstringThe customer identifier
Body FieldTypeDescription
reasonstringReason for erasure (default: “GDPR full erasure request”)
Example
curl -X DELETE "https://salesbooth.com/api/v1/gdpr/full_erase?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "Customer right to be forgotten request"}'
GET /api/v1/gdpr/verify
Verify that a customer’s data has been completely erased. Scans all tables for remaining PII and returns a verification report.
ParameterTypeDescription
customer_id requiredstringThe customer identifier to verify
Example
curl "https://salesbooth.com/api/v1/gdpr/verify?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Consent Management

Record, retrieve, withdraw, and renew consent for specific processing purposes.

GET /api/v1/gdpr/consent
Retrieve consent records for a customer. Returns all consent entries with their current status and the list of valid consent purposes.
ParameterTypeDescription
customer_id requiredstringThe customer identifier
active_onlystringSet to true to return only active consents
Example
curl "https://salesbooth.com/api/v1/gdpr/consent?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/gdpr/consent
Record a new consent grant for a customer and purpose. Supports optional channel and consent version metadata.
FieldTypeDescription
customer_id requiredstringThe customer identifier
purpose requiredstringProcessing purpose (e.g. marketing, analytics, necessary)
channelstringHow consent was collected (default: api)
metadataobjectAdditional context about the consent
consent_versionstringVersion of the consent policy
Example
curl -X POST https://salesbooth.com/api/v1/gdpr/consent \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "purpose": "marketing", "channel": "web_form", "consent_version": "2.0" }'
DELETE /api/v1/gdpr/consent
Withdraw an existing consent record for a customer and purpose.
ParameterTypeDescription
customer_id requiredstringThe customer identifier
Body FieldTypeDescription
purpose requiredstringThe consent purpose to withdraw
Example
curl -X DELETE "https://salesbooth.com/api/v1/gdpr/consent?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"purpose": "marketing"}'
POST /api/v1/gdpr/consent_withdraw_all
Batch withdraw all active consent records for a customer in a single operation.
FieldTypeDescription
customer_id requiredstringThe customer identifier
reasonstringReason for withdrawal (default: “Batch consent withdrawal”)
Example
curl -X POST https://salesbooth.com/api/v1/gdpr/consent_withdraw_all \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"customer_id": "cust_xxxxx", "reason": "Customer opted out"}'
POST /api/v1/gdpr/consent_renew
Extend the expiration of an existing consent record for a customer and purpose. Creates a new audit entry distinct from the initial grant.
FieldTypeDescription
customer_id requiredstringThe customer identifier
purpose requiredstringThe consent purpose to renew
channelstringRenewal channel (default: api)
expiration_monthsintegerCustom expiration period in months (uses purpose default if omitted)
Example
curl -X POST https://salesbooth.com/api/v1/gdpr/consent_renew \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"customer_id": "cust_xxxxx", "purpose": "marketing", "expiration_months": 12}'
POST /api/v1/gdpr/consent_renew_all
Renew all active or expired (non-withdrawn) consents for a customer in a single operation.
FieldTypeDescription
customer_id requiredstringThe customer identifier
channelstringRenewal channel (default: api)
Example
curl -X POST https://salesbooth.com/api/v1/gdpr/consent_renew_all \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"customer_id": "cust_xxxxx", "channel": "re-consent-campaign"}'
GET /api/v1/gdpr/consent_expiring
Returns consent records that will expire within the specified number of days. Useful for triggering re-consent campaigns before expiry.
ParameterTypeDescription
days_aheadintegerLook-ahead window in days (default: 30, max: 365)
limitintegerMaximum records to return (default: 100, max: 500)
Example
curl "https://salesbooth.com/api/v1/gdpr/consent_expiring?days_ahead=14" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/consent_health
Returns aggregate consent health metrics including active, expiring, expired, and withdrawn counts with an overall health percentage score.
Example
curl https://salesbooth.com/api/v1/gdpr/consent_health \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/consent_expiration_config
Returns the per-purpose consent expiration configuration for the current tenant, merged with global defaults.
Example
curl https://salesbooth.com/api/v1/gdpr/consent_expiration_config \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/gdpr/consent_expiration_config
Set the default expiration period for a specific consent purpose for the current tenant.
FieldTypeDescription
purpose requiredstringThe consent purpose to configure
expiration_months requiredintegerExpiration period in months (1–120)
Example
curl -X POST https://salesbooth.com/api/v1/gdpr/consent_expiration_config \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"purpose": "marketing", "expiration_months": 12}'
GET /api/v1/gdpr/consent_purposes
Returns all valid consent purposes with human-readable labels and default expiration periods in months.
Example
curl https://salesbooth.com/api/v1/gdpr/consent_purposes \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Retention Policies

View and manage data retention policies. Retention policies control how long different types of data are kept before automatic cleanup.

GET /api/v1/gdpr/retention
Returns all data retention policies for the current tenant, along with valid data types.
Example
curl https://salesbooth.com/api/v1/gdpr/retention \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
PATCH /api/v1/gdpr/retention
Creates or updates a data retention policy for a specific data type.
FieldTypeDescription
data_type requiredstringThe data type to configure retention for
retention_days requiredintegerNumber of days to retain data
is_activebooleanWhether the policy is active (default: true)
Example
curl -X PATCH https://salesbooth.com/api/v1/gdpr/retention \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "data_type": "audit_logs", "retention_days": 730, "is_active": true }'

Compliance Monitoring

Dashboards, reports, and audit evidence for GDPR compliance oversight.

GET /api/v1/gdpr/dashboard
Returns aggregate compliance data: consent health metrics, recent DSARs (last 30 days), and erasure statistics. Suitable for the compliance overview panel.
Example
curl https://salesbooth.com/api/v1/gdpr/dashboard \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/register
Returns all active entries from the data processing register (Art. 30 Records of Processing Activities). Includes data categories, processing purposes, legal bases, retention periods, and data recipients.
Example
curl https://salesbooth.com/api/v1/gdpr/register \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/erasure_log
Returns paginated list of erasure and export audit log entries for the current tenant.
ParameterTypeDescription
offsetintegerNumber of entries to skip (default: 0)
limitintegerMaximum entries to return (default: 50, max: 100)
Example
curl "https://salesbooth.com/api/v1/gdpr/erasure_log?limit=25" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/search
Search customers by name, email, or ID using blind indexes, and overlay compliance context per result: active consent count and consent purposes held.
ParameterTypeDescription
q requiredstringSearch query (name, email, or customer ID)
limitintegerMaximum results (default: 10, max: 20)
Example
curl "https://salesbooth.com/api/v1/gdpr/search?q=jane%40example.com" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/gdpr/audit_evidence
Returns a structured compliance evidence report for a given date range, including DSAR log, erasure summary, consent health snapshot, and retention policies. Suitable for regulator submission.
ParameterTypeDescription
date_fromstringStart of date range, YYYY-MM-DD (defaults to 30 days ago)
date_tostringEnd of date range, YYYY-MM-DD (defaults to today)
Example
curl "https://salesbooth.com/api/v1/gdpr/audit_evidence?date_from=2026-01-01&date_to=2026-03-31" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"

Compliance & GDPR Flows

Step-by-step consent lifecycle and data subject request (DSAR) flows with complete curl examples. All compliance actions are logged in the immutable audit trail for regulatory evidence.

Consent Lifecycle

Consent follows a four-step lifecycle: record → check → withdraw → renew. All steps are idempotent and generate audit trail entries.

Step 1 — Record consent at sign-up

curl -X POST https://salesbooth.com/api/v1/gdpr/consent \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "purpose": "marketing_email", "channel": "web_form", "consent_version": "2.1", "metadata": { "ip": "1.2.3.4", "form": "signup" } }'

Step 2 — Check active consents before sending

curl "https://salesbooth.com/api/v1/gdpr/consent?customer_id=cust_xxxxx&active_only=true" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" # Response includes: # { "consents": [{ "purpose": "marketing_email", "status": "active", # "expires_at": "2028-03-01", ... }], # "valid_purposes": ["marketing_email", "marketing_sms", ...] }

Step 3 — Withdraw consent on unsubscribe

curl -X DELETE "https://salesbooth.com/api/v1/gdpr/consent?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"purpose": "marketing_email"}'

Step 4 — Renew consent before expiry

curl -X POST https://salesbooth.com/api/v1/gdpr/consent_renew \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cust_xxxxx", "purpose": "marketing_email", "channel": "re-consent-email", "expiration_months": 24 }'

Data Export Flow (Art. 15/20)

Export all data held about a customer in portable JSON format. The export is logged in the audit trail.

# Request export curl "https://salesbooth.com/api/v1/gdpr/export?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" # Response shape: # { "export": { # "customer": { "customer_id": "cust_xxxxx", "name": "...", "email": "...", ... }, # "deals": [...], # "contracts": [...], # "consents": [...], # "audit_trail": [...], # "exported_at": "2026-03-18T10:00:00+00:00" # } # }

Erasure Flow (Art. 17)

Erase a customer’s PII. Financial records are anonymised (not deleted) to preserve accounting integrity. Use /gdpr/verify to confirm erasure completion.

# Request erasure curl -X DELETE "https://salesbooth.com/api/v1/gdpr/full_erase?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{"reason": "Customer exercised right to be forgotten"}' # Verify erasure curl "https://salesbooth.com/api/v1/gdpr/verify?customer_id=cust_xxxxx" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" # Verify response includes a verification_hash for the audit record: # { "verification": { # "erased": true, # "tables_checked": 12, # "pii_remaining": 0, # "verification_hash": "sha256:a1b2c3..." # } # }

Audit Trail Integrity

Every audit entry is linked to the previous one via a SHA-256 hash chain, forming a tamper-evident log. The hash formula is:

entry_hash = SHA256( entity_type + entity_id + action + changes_json + snapshot_json + previous_hash <-- links to previous entry + created_at )

Any attempt to modify or delete an entry breaks the chain. The GET /api/v1/audit?action=verify&entity_type=customer&entity_id=cust_xxxxx endpoint re-computes the chain and returns a status of intact or tampered.

Compliance Evidence

Enterprise procurement and legal teams require structured evidence of GDPR compliance before approving software vendors. The compliance evidence endpoint returns a point-in-time package covering all key compliance dimensions.

GET /api/v1/gdpr/compliance_evidence
Returns a structured compliance package suitable for enterprise procurement reviews and regulator submission. Covers retention policy status, consent statistics per purpose, recent erasure log with verification hashes, audit trail integrity check (hash chain), and data processing register summary (Art. 30 ROPA).
Required scope
customers:read
Example request
curl https://salesbooth.com/api/v1/gdpr/compliance_evidence \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response shape
{ "error": false, "success": true, "data": { "evidence": { "report_type": "compliance_evidence", "generated_at": "2026-03-18T10:00:00+00:00", "tenant_id": "tenant_xxxxx", "retention_policies": { "policies": [ { "data_type": "audit_logs", "retention_days": 730, "is_active": true, "compliance_status": "active" } ], "overall_compliant": true, "policy_count": 5 }, "consent_statistics": { "by_purpose": { "marketing_email": { "granted": 1420, "withdrawn": 83, "expired": 12, "expiring_soon": 47, "total": 1562 }, "analytics": { "granted": 1380, "withdrawn": 31, "expired": 8, "expiring_soon": 22, "total": 1441 } }, "purpose_count": 6 }, "erasure_log": { "recent_entries": [ { "log_id": "audit_abc123", "entity_id": "cust_xxxxx", "action": "erased", "actor_type": "api_key", "entry_hash": "sha256:a1b2c3...", "created_at": "2026-03-15 09:12:00" } ], "entry_count": 12 }, "audit_integrity": { "status": "verified", // "verified" | "broken" | "unavailable" "checked_entries": 100, "broken_entries": 0, "sample_size": 100 }, "data_processing_register": { "total_entries": 8, "data_categories": ["contact_data", "financial_data", "usage_data"], "legal_bases": ["consent", "contract", "legitimate_interest"] } } } }

Enterprise tip: Run this endpoint quarterly and store the response as a compliance snapshot. The audit_integrity.status field is especially useful for demonstrating tamper-evidence to auditors. A broken status triggers an immediate security review.

Webhook Signature Verification

Every webhook delivery includes two headers: X-Salesbooth-Signature (HMAC-SHA256 of the timestamp + raw body) and X-Salesbooth-Timestamp (Unix timestamp of delivery). Verify both before processing any webhook payload to prevent spoofed and replayed requests.

Algorithm: v1= + HMAC-SHA256(webhook_secret, timestamp + "." + raw_request_body). The webhook secret is per-webhook and is set at creation time. Never log or expose the secret. Rotate it from the webhook settings page if compromised.

Verification — PHP

PHP
<?php define('WEBHOOK_SECRET', getenv('SALESBOOTH_WEBHOOK_SECRET')); define('TOLERANCE_SECONDS', 300); // Read the raw request body (must be read BEFORE parsing JSON) $rawBody = file_get_contents('php://input'); // Get the signature and timestamp headers $signature = $_SERVER['HTTP_X_SALESBOOTH_SIGNATURE'] ?? ''; $ts = $_SERVER['HTTP_X_SALESBOOTH_TIMESTAMP'] ?? ''; // Replay protection: reject events older than 5 minutes if (abs(time() - (int) $ts) > TOLERANCE_SECONDS) { http_response_code(400); exit(json_encode(['error' => 'Timestamp out of tolerance'])); } // Compute expected signature: v1= + HMAC-SHA256(timestamp.body, secret) $signedContent = $ts . '.' . $rawBody; $expected = 'v1=' . hash_hmac('sha256', $signedContent, WEBHOOK_SECRET); // Constant-time comparison to prevent timing attacks if (!hash_equals($expected, $signature)) { http_response_code(401); exit(json_encode(['error' => 'Invalid signature'])); } // Safe to parse and process the payload $event = json_decode($rawBody, true); $eventType = $event['event']; // e.g. "deal.closed" $data = $event['data']; switch ($eventType) { case 'deal.closed': // Handle deal closure break; case 'customer.deleted': // Handle GDPR erasure notification break; }

Verification — Python

Python
import hmac import hashlib import os import time from flask import Flask, request, abort import json app = Flask(__name__) WEBHOOK_SECRET = os.environ['SALESBOOTH_WEBHOOK_SECRET'] TOLERANCE_SECONDS = 300 @app.route('/webhook', methods=['POST']) def webhook(): # Read raw body before any parsing raw_body = request.get_data() # Get signature and timestamp headers signature = request.headers.get('X-Salesbooth-Signature', '') ts = request.headers.get('X-Salesbooth-Timestamp', '0') # Replay protection: reject events older than 5 minutes if abs(time.time() - int(ts)) > TOLERANCE_SECONDS: abort(400, 'Timestamp out of tolerance') # Compute expected signature: v1= + HMAC-SHA256(timestamp.body, secret) signed_content = f"{ts}.".encode('utf-8') + raw_body expected = 'v1=' + hmac.new( WEBHOOK_SECRET.encode('utf-8'), signed_content, hashlib.sha256 ).hexdigest() # Constant-time comparison if not hmac.compare_digest(expected, signature): abort(401, 'Invalid signature') event = json.loads(raw_body) event_type = event.get('event') # e.g. "deal.closed" data = event.get('data') if event_type == 'deal.closed': handle_deal_closed(data) elif event_type == 'customer.deleted': handle_customer_deletion(data) return '', 200

Verification — JavaScript (Node.js)

JavaScript (Express)
import express from 'express'; import crypto from 'crypto'; const app = express(); const WEBHOOK_SECRET = process.env.SALESBOOTH_WEBHOOK_SECRET; const TOLERANCE_SECONDS = 300; // IMPORTANT: Use express.raw() to get the raw body before any JSON parsing app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const rawBody = req.body; // Buffer from express.raw() const signature = req.headers['x-salesbooth-signature'] || ''; const timestamp = req.headers['x-salesbooth-timestamp'] || '0'; // Replay protection: reject events older than 5 minutes const age = Math.floor(Date.now() / 1000) - parseInt(timestamp, 10); if (age > TOLERANCE_SECONDS) { return res.status(400).json({ error: 'Timestamp out of tolerance' }); } // Compute expected signature: v1= + HMAC-SHA256(timestamp.body, secret) const signedContent = `${timestamp}.${rawBody.toString('utf8')}`; const expected = 'v1=' + crypto .createHmac('sha256', WEBHOOK_SECRET) .update(signedContent, 'utf8') .digest('hex'); // Constant-time comparison to prevent timing attacks if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) { return res.status(401).json({ error: 'Invalid signature' }); } const event = JSON.parse(rawBody.toString()); const { event: eventType, data } = event; switch (eventType) { case 'deal.closed': handleDealClosed(data); break; case 'customer.deleted': handleCustomerDeleted(data); break; } res.status(200).end(); });

Security notes:

  • Always read the raw body before any JSON parsing — even whitespace differences will invalidate the signature.
  • Include both the timestamp and body in the signed content (timestamp + "." + raw_body) and prefix the result with v1=.
  • Reject stale events where X-Salesbooth-Timestamp is older than 300 seconds to prevent replay attacks.
  • Use constant-time comparison (hash_equals in PHP, hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js) to prevent timing attacks.
  • Return 2xx quickly and process asynchronously — webhooks time out after 10 seconds.
  • Implement idempotency using event_id to handle duplicate deliveries.

Customer Authentication

Magic-link authentication for the Customer Portal. Customers receive a time-limited login link via email and exchange it for a short-lived JWT session. No seller API key is required — this endpoint is fully public.

Rate limiting: Magic-link requests are limited to 3 per minute per email+IP to prevent enumeration. A 200 response is returned even when the email is not found.

POST /api/v1/customer-auth?action=request-access
Send a magic-link login email to a customer. Returns 200 regardless of whether the email exists to prevent enumeration.
FieldTypeDescription
email requiredstringCustomer email address
Example
curl -X POST https://salesbooth.com/api/v1/customer-auth?action=request-access \ -H "Content-Type: application/json" \ -d '{ "email": "customer@example.com" }'
Response
{ "error": false, "success": true, "data": { "message": "If this email is registered, a login link has been sent." } }
POST /api/v1/customer-auth?action=verify
Exchange a magic-link token (from the email link) for a JWT access token and refresh token.
FieldTypeDescription
token requiredstringOne-time token from the magic link
Example
curl -X POST https://salesbooth.com/api/v1/customer-auth?action=verify \ -H "Content-Type: application/json" \ -d '{ "token": "clat_xxxxxxxxxxxxxxxxxxxxxxxx" }'
Response
{ "error": false, "success": true, "data": { "access_token": "eyJ...", "refresh_token": "clar_xxxxxxxxxxxxxxxx", "expires_in": 3600, "customer_id": "cust_xxxxx", "tenant_id": "tenant_xxxxx" } }
POST /api/v1/customer-auth?action=refresh
Refresh an expired access token using the refresh token.
FieldTypeDescription
refresh_token requiredstringRefresh token from the verify response
POST /api/v1/customer-auth?action=logout
Revoke the current customer session.

Customer Portal

Authenticated self-service endpoints for buyers. All requests require a valid customer JWT issued by Customer Authentication sent as a Bearer token. Covers deal viewing, contract signing, payment, and profile management.

Authentication: Authorization: Bearer <customer_jwt> — use the JWT from the verify response, not a seller API key.

GET /api/v1/customer-portal?action=my-deals
List all deals belonging to the authenticated customer.
ParameterTypeDescription
statusstringFilter by deal status
limitintegerMax results (default: 20)
offsetintegerPagination offset
GET /api/v1/customer-portal?action=deal&id={deal_id}
Get full deal details including line items, terms, and current status.
GET /api/v1/customer-portal?action=contract&deal_id={deal_id}
Retrieve the signed contract document for a deal.
POST /api/v1/customer-portal?action=sign
Digitally sign a contract to accept the deal terms.
FieldTypeDescription
deal_id requiredstringDeal to sign
signature_name requiredstringCustomer’s full name as signature
agreed requiredbooleanMust be true to accept terms
POST /api/v1/customer-portal?action=create-payment-intent
Create a Stripe PaymentIntent for a deal. Returns the client_secret needed by Stripe.js to complete the payment on the buyer’s side.
FieldTypeDescription
deal_id requiredstringDeal to pay for
POST /api/v1/customer-portal?action=confirm-payment
Confirm payment completion after Stripe.js has collected and processed payment details.
FieldTypeDescription
deal_id requiredstringDeal identifier
payment_intent_id requiredstringStripe PaymentIntent ID
GET /api/v1/customer-portal?action=profile
Get the customer’s own profile data.
PATCH /api/v1/customer-portal?action=profile
Update the customer’s profile fields.
FieldTypeDescription
namestringDisplay name
phonestringPhone number
companystringCompany name
GET /api/v1/customer-portal?action=my-subscriptions
List all active and past recurring subscriptions for the customer.

Deal Discovery

Enables AI agents to search and browse available deal offers programmatically. Unlike the Agent Discovery admin API (merchant control plane), this endpoint is agent-facing — it returns offers that the seller has marked as agent-discoverable, filtered by the agent’s criteria.

Required scope: agent:discover

Also available via MCP: The discover_deals MCP tool exposes the same data in a structured format for Claude and other MCP-compatible agents. See MCP Protocol.

GET /api/v1/deal-discovery
Discover agent-visible deal offers with optional filters. Returns only products and deals that the merchant has explicitly enabled for agent discovery.
ParameterTypeDescription
categorystringFilter by product category
min_pricenumberMinimum deal price
max_pricenumberMaximum deal price
currencystringISO 4217 currency code (e.g. USD)
pricing_modelstringFilter by pricing model type
limitintegerMax results (default: 50, max: 100)
offsetintegerPagination offset
Example
curl "https://salesbooth.com/api/v1/deal-discovery?category=software&max_price=5000¤cy=USD" \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "deals": [ { "deal_id": "deal_xxxxx", "title": "Enterprise Software Suite", "price": 2999.00, "currency": "USD", "category": "software", "negotiable": true, "terms_schema_url": "/api/v1/schema/deal-terms" } ], "pagination": { "total": 42, "limit": 50, "offset": 0, "count": 1 } } }
GET /api/v1/deal-discovery?action=schema
Retrieve the JSON Schema defining the structure of discoverable deal terms. Use this to validate deal proposals programmatically before submitting. See also Machine-Readable Schemas.

Quotes & Invoices

Generate shareable quotes and invoices from deals. Quotes have a configurable validity window; invoices are permanent records. Both are retrievable via a short code without authentication, making them safe to share directly with customers.

Required scope: deals:read to generate quotes, deals:write to generate invoices. Short-code retrieval is unauthenticated.

POST /api/v1/quotes?action=generate_quote
Generate a quote from a deal. Returns a short code and shareable URL the customer can visit to view and accept the quote.
FieldTypeDescription
deal_id requiredstringDeal to generate quote for
validity_daysintegerDays until quote expires (default: 30)
Example
curl -X POST https://salesbooth.com/api/v1/quotes?action=generate_quote \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "validity_days": 14 }'
Response
{ "error": false, "success": true, "data": { "quote_id": "qte_xxxxx", "short_code": "q7f3a1b2", "share_url": "https://salesbooth.com/quote/q7f3a1b2", "expires_at": "2026-03-29T00:00:00Z", "total": 2999.00, "currency": "USD" } }
POST /api/v1/quotes?action=generate_invoice
Generate a formal invoice from a closed deal.
FieldTypeDescription
deal_id requiredstringClosed deal to invoice
GET /api/v1/quotes?short_code={code}
Retrieve a quote or invoice by its short code. No authentication required. Used by the customer-facing quote viewing page.
ParameterTypeDescription
short_code requiredstringThe short code from the generate response
GET /api/v1/quotes?deal_id={deal_id}
List all quotes generated for a deal. Requires authentication.

Deal Notifications

Send transactional notifications to customers about deal activity. Supports email and SMS channels based on customer contact preferences. Used by agents and automations to deliver quote links, payment reminders, and deal updates.

Required scope: customers:read (GET), deals:write (POST)

Rate limit: 10 notifications per hour per API key.

GET /api/v1/deal-notifications?customer_id={id}
Get a customer’s notification channel preferences and recent notification history before sending.
ParameterTypeDescription
customer_id requiredstringCustomer to check
Response
{ "error": false, "success": true, "data": { "preferred_channel": "email", "has_email": true, "has_phone": false, "marketing_consent": true, "recent_notifications": [...] } }
POST /api/v1/deal-notifications
Send a transactional notification to a customer about a deal.
FieldTypeDescription
deal_id requiredstringRelated deal
type requiredstringquote_sent, invoice_sent, payment_reminder, deal_update, terms_updated
messagestringOptional custom message body
Example
curl -X POST https://salesbooth.com/api/v1/deal-notifications \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "deal_id": "deal_abc123", "type": "quote_sent", "message": "Your quote is ready — view it at https://salesbooth.com/quote/q7f3a1b2" }'

Pricing Simulation

Read-only pricing tools for agents to model bundle discounts, compare cart scenarios, and analyse historical negotiation patterns — without creating real deals. Useful for recommending the optimal product configuration to buyers.

Required scope: products:read

All simulation responses include "simulation_only": true to confirm no data was written.

POST /api/v1/simulate-pricing
Simulate bundle pricing for a cart. Applies all matching bundle discount rules and promo codes without creating a deal.
FieldTypeDescription
items requiredarrayArray of { product_id, quantity, option_ids? }
currencystringISO 4217 code (default: USD)
promo_codestringOptional promo code to test
Example
curl -X POST https://salesbooth.com/api/v1/simulate-pricing \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "product_id": "prod_aaa", "quantity": 2 }, { "product_id": "prod_bbb", "quantity": 1 } ], "currency": "USD", "promo_code": "SAVE20" }'
Response
{ "error": false, "success": true, "data": { "items": [...], "subtotal": 450.00, "bundle_discounts": [{ "rule": "3-for-2 Bundle", "amount": 45.00 }], "bundle_discount_total": 45.00, "promo_discount": 81.00, "total": 324.00, "currency": "USD", "savings_vs_individual": 126.00, "simulation_only": true } }
POST /api/v1/simulate-pricing/compare
Compare pricing across multiple cart scenarios side-by-side. Useful for agents presenting options to buyers.
FieldTypeDescription
scenarios requiredarrayArray of { label, items } scenario objects
currencystringISO 4217 currency code
GET /api/v1/simulate-pricing
Retrieve aggregated negotiation patterns for a product or category. Returns win rates, average discount depth, and deal velocity to inform agent negotiation strategy.
ParameterTypeDescription
product_idstringAnalyse patterns for a specific product
categorystringAnalyse patterns for a product category
period_daysintegerLookback window in days (1–365, default: 90)

Real-Time Events (SSE)

Subscribe to a real-time stream of deal events via Server-Sent Events (SSE). Use this to power live dashboards, notification UIs, or trigger agent actions without polling. The stream requires authentication and emits events for all event types the key has access to.

Protocol: Server-Sent Events (text/event-stream)

Max stream duration: 60 minutes. A reconnect event is sent before the connection closes so your client can reconnect from the last event.

Heartbeat: A heartbeat comment is sent every 15 seconds to keep the connection alive through load balancers and proxies.

GET /api/v1/events/stream
Open a Server-Sent Events stream. Set Accept: text/event-stream and keep the connection open to receive events as they occur.
ParameterTypeDescription
eventsstringComma-separated event types to subscribe to (e.g. deal.updated,negotiation.countered). Omit for all.
deal_idstringFilter events to a specific deal
customer_idstringFilter events for a specific customer
last_event_idstringResume from this event ID (also accepted via Last-Event-ID header)
Example (curl)
curl -N "https://salesbooth.com/api/v1/events/stream?events=deal.updated,deal.closed" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Accept: text/event-stream"
Example (JavaScript EventSource)
const es = new EventSource( '/api/v1/events/stream?events=deal.updated', { headers: { 'Authorization': 'Bearer sb_test_example_key_do_not_use' } } ); es.addEventListener('deal.updated', (e) => { const event = JSON.parse(e.data); console.log('Deal updated:', event.deal_id); }); es.addEventListener('reconnect', (e) => { const { last_event_id } = JSON.parse(e.data); // Reconnect with ?last_event_id= to resume });
Stream event format
event: connected data: {"status":"connected","connection_id":"conn_xxxxx","heartbeat_interval":15} event: deal.updated data: {"deal_id":"deal_abc","status":"negotiating","_timestamp":"2026-03-15T10:30:00Z","_signature":"sha256=..."} event: heartbeat data: comment event: reconnect data: {"reason":"timeout","last_event_id":"seq:1234"}

Widget A/B Tests

Run controlled experiments across two widget variants to optimise conversion. Traffic is split between the original widget (Variant A) and a challenger (Variant B) with configurable traffic weighting. Statistical significance is computed automatically.

Required scope: deals:read (GET), deals:write (POST/PATCH)

Public resolve endpoint: GET /api/v1/ab-tests/resolve?api_key=sb_pub_... — called by the widget loader on each page load to determine which variant to show. No secret key required.

GET /api/v1/ab-tests
List A/B tests for the tenant, or retrieve a specific test with live statistics including chi-squared significance and per-variant revenue.
ParameterTypeDescription
idstringRetrieve a specific test with full stats
Example
curl https://salesbooth.com/api/v1/ab-tests \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
POST /api/v1/ab-tests
Create a new A/B test for a widget. A second variant widget is automatically cloned from the source with the provided overrides applied.
FieldTypeDescription
widget_id requiredstringSource (Variant A) widget
namestringDescriptive test name (auto-generated from widget title if omitted)
traffic_weight_bintegerPercentage of traffic to send to Variant B (default: 50)
auto_promotebooleanAuto-promote winner when significance threshold is reached
variant_b_titlestringOverride widget title for Variant B
variant_b_cta_textstringOverride CTA button text for Variant B
variant_b_theme_colorstringOverride theme colour hex for Variant B
Example
curl -X POST https://salesbooth.com/api/v1/ab-tests \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "widget_id": "wgt_xxxxx", "name": "CTA Button Colour Test", "traffic_weight_b": 50, "auto_promote": true, "variant_b_cta_text": "Get Your Quote Now", "variant_b_theme_color": "#10b981" }'
PATCH /api/v1/ab-tests?id={ab_test_id}
Pause, resume, or adjust traffic split for a running test.
FieldTypeDescription
statusstringrunning or paused
traffic_weight_bintegerAdjusted traffic percentage for Variant B
POST /api/v1/ab-tests/promote
Promote the winning variant to become the canonical widget for the site. Closes the test.
FieldTypeDescription
ab_test_id requiredstringTest to close
winner_widget_id requiredstringWidget ID of the winning variant
GET /api/v1/ab-tests/resolve?api_key=sb_pub_...
Resolve which widget variant a visitor should see. Called automatically by the widget loader on each page load. Public endpoint — uses a publishable key only.
Response
{ "error": false, "success": true, "data": { "variant": "A", "widget_id": "wgt_xxxxx", "ab_test_id": "abt_xxxxx", "config": { "title": "Create a Deal", "theme_color": "#2563eb" } } }

Widget Public Endpoints

These three endpoints are called directly by the <salesbooth-deal> widget using a publishable API key (sb_pub_*). They can also be called from custom storefront code to build headless checkout flows.

GET /api/v1/widget-intelligence
Returns aggregated, privacy-safe product intelligence for the widget: popularity badges, most-chosen option defaults, deal price distribution, and win-probability context. Used to pre-select options and display social proof without exposing individual transaction data.
ParameterTypeDescription
api_key requiredstringPublishable key (sb_pub_*)
productsstringComma-separated product IDs to analyse (falls back to widget config)
Example
curl "https://salesbooth.com/api/v1/widget-intelligence?api_key=sb_pub_xxxxx&products=prod_aaa,prod_bbb"
Response
{ "error": false, "success": true, "data": { "products": { "prod_aaa": { "rank": 1, "badge": "most_popular", "closed_deal_count": 142 }, "prod_bbb": { "rank": 2, "badge": null, "closed_deal_count": 87 } }, "option_defaults": { "prod_aaa": { "tier": { "value": "pro", "selection_rate": 68, "should_preselect": true } } }, "price_context": { "avg_deal_value": 420.00, "min_deal_value": 99.00, "max_deal_value": 999.00 } } }
POST /api/v1/widget-contract?action=generate
Generate contract HTML from a template during the widget checkout flow. The rendered HTML is shown to the buyer before they digitally sign. Authenticated with a publishable key.
FieldTypeDescription
api_key requiredstringPublishable key (sb_pub_*)
deal_id requiredstringDeal to generate contract for
customer_namestringBuyer name for template personalisation
customer_emailstringBuyer email for template personalisation
POST /api/v1/widget-contract?action=sign
Record a digital signature on a generated contract. Accepts typed name, checkbox acceptance, or drawn signature (base64 PNG).
FieldTypeDescription
contract_id requiredstringContract from the generate response
deal_id requiredstringAssociated deal
signer_name requiredstringFull legal name of the signer
signer_email requiredstringSigner’s email address
signature_modestringcheckbox, type, or draw
signature_imagestringBase64 PNG data URI for drawn signatures
POST /api/v1/widget-discount
Validate a promo code during widget checkout and return the discount to apply. Rate-limited to 10 attempts per minute per IP to prevent code enumeration. Authenticated with a publishable key via Bearer header.
FieldTypeDescription
code requiredstringPromo code entered by the buyer
subtotal requirednumberCart subtotal to calculate the discount amount against
Example
curl -X POST https://salesbooth.com/api/v1/widget-discount \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "code": "SAVE20", "subtotal": 450.00 }'
Response
{ "error": false, "success": true, "data": { "valid": true, "discount": { "type": "percentage", "value": 20, "code": "SAVE20", "amount": 90.00, "description": "20% off your first purchase" } } }
POST /api/v1/widget-validate
Validates a product configuration for a headless widget session. Checks compatibility rules (requires / excludes) and returns any price adjustments from includes_price rules. Call this before creating a deal to surface configuration errors early. Authenticated with a publishable key via Bearer header.
FieldTypeDescription
product_id requiredstringProduct to validate the configuration for
option_idsstring[]Array of selected option IDs to validate against compatibility rules
Example
curl -X POST https://salesbooth.com/api/v1/widget-validate \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_aaa", "option_ids": ["opt_pro", "opt_annual"] }'
Response
{ "error": false, "success": true, "data": { "valid": true, "errors": [], "warnings": [], "price_adjustments": [ { "rule_id": 12, "option_id": "opt_annual", "adjusted_price": 0.00, "reason": "Price included with option opt_pro" } ] } }
POST /api/v1/widget-payment-preview
Previews the full payment breakdown for a headless widget cart: subtotal, option modifiers, promo code discount, tax, total, and the actual charge amount (which may be a deposit rather than the full total depending on the widget configuration). Use this to display an accurate payment summary before initiating checkout. Rate-limited to 30 requests per minute per IP. Authenticated with a publishable key via Bearer header.
FieldTypeDescription
product_id requiredstringProduct to calculate pricing for
option_idsstring[]Selected option IDs — their price modifiers are included in the subtotal
quantityintegerNumber of units (default: 1)
promo_codestringOptional promo code to factor into the discount calculation
Example
curl -X POST https://salesbooth.com/api/v1/widget-payment-preview \ -H "Authorization: Bearer sb_pub_xxxxx" \ -H "Content-Type: application/json" \ -d '{ "product_id": "prod_aaa", "option_ids": ["opt_pro"], "quantity": 1, "promo_code": "SAVE20" }'
Response
{ "error": false, "success": true, "data": { "subtotal": 450.00, "discount": 90.00, "tax": 29.52, "total": 389.52, "chargeAmount": 97.38, "isDeposit": true, "currency": "USD" } }

FX Rates

Retrieve real-time exchange rates between any two currencies. Used by the widget for multi-currency price display and by agents for cross-currency deal valuation. No authentication required.

Rate limit: 100 requests per hour per IP. Rates are cached server-side — use the fetched_at field to determine freshness.

GET /api/v1/fx-rate
Return the current exchange rate from one currency to another.
ParameterTypeDescription
from requiredstringSource currency (ISO 4217, e.g. AUD)
to requiredstringTarget currency (ISO 4217, e.g. USD)
Example
curl "https://salesbooth.com/api/v1/fx-rate?from=AUD&to=USD"
Response
{ "error": false, "success": true, "data": { "from": "AUD", "to": "USD", "rate": 0.6512, "provider": "open-exchange", "fetched_at": "2026-03-15T10:00:00Z" } }

Machine-Readable Schemas

Public JSON Schema and state machine definitions for AI agents and integrators to understand deal structure programmatically. These endpoints require no authentication and are designed to be fetched and cached by agent frameworks.

No authentication required. Responses include Cache-Control headers — schemas change infrequently so aggressive caching is safe.

Rate limit: 30 requests per minute per IP.

GET /api/v1/schema/state-machine
Returns machine-readable state machine definitions for deals and contracts: all valid states, allowed transitions, and the conditions required for each transition. Use this to validate state changes before making API calls.
ParameterTypeDescription
entitystringdeals or contracts (omit for both)
Example
curl "https://salesbooth.com/api/v1/schema/state-machine?entity=deals"
Response (abbreviated)
{ "error": false, "success": true, "data": { "schema_version": "1.0.0", "entity_types": ["deals", "contracts"], "deals": { "states": ["draft", "open", "negotiating", "accepted", "signed", "closed", "cancelled"], "transitions": [ { "from": "draft", "to": "open", "action": "publish", "conditions": ["has_product", "has_customer"] }, { "from": "negotiating", "to": "accepted", "action": "accept", "conditions": [] } ] } } }
GET /api/v1/schema/deal-terms
Returns a JSON Schema document describing the structure of deal terms. Agents use this to validate proposed terms before submitting a negotiation or deal creation request.
Example
curl "https://salesbooth.com/api/v1/schema/deal-terms"
Response (abbreviated)
{ "error": false, "success": true, "data": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "DealTerms", "type": "object", "properties": { "price": { "type": "number", "minimum": 0 }, "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, "payment_terms": { "type": "string", "enum": ["immediate", "net_30", "net_60"] }, "discount_percent": { "type": "number", "minimum": 0, "maximum": 100 } }, "required": ["price", "currency"] } }

Object Schemas

Human-readable field definitions for the core resource objects returned by the API.

Deal Object

FieldTypeDescription
idstringUnique identifier, prefix deal_
tenant_idstringTenant that owns the deal
customer_idstringAssociated customer identifier
titlestringHuman-readable deal name (max 255 chars)
descriptionstringOptional deal description
statusenumdraft · in_progress · pending_signature · pending_payment · closed · cancelled
deal_typeenumone_time or recurring
currencystringISO 4217 currency code (e.g. USD)
tax_ratedecimalTax rate (stored as 0.1000 for 10%)
subtotaldecimalSum of line items before tax — calculated, read-only
totaldecimalSubtotal + tax — calculated, read-only
line_itemsarrayArray of line item objects (see below)
metadataobjectArbitrary key-value pairs (max depth 3)
versionintegerOptimistic lock version; pass in If-Match on PATCH
created_atISO 8601Creation timestamp
updated_atISO 8601Last modification timestamp
Line Item Object
{ "id": "item_xxxxx", "deal_id": "deal_xxxxx", "product_id": "prod_xxxxx", "quantity": 2, "unit_price": "499.00", "discount": "10.00", "line_total": "888.20" }

Customer Object

FieldTypeDescription
idstringUnique identifier, prefix cust_
namestringFull name (encrypted at rest)
emailstringEmail address (encrypted at rest)
phonestringPhone number (encrypted at rest, optional)
companystringCompany or organisation name
metadataobjectArbitrary key-value pairs
created_atISO 8601Creation timestamp
updated_atISO 8601Last modification timestamp

Product Object

FieldTypeDescription
idstringUnique identifier, prefix prod_
namestringProduct display name
descriptionstringProduct description
pricedecimalBase price (subject to configured pricing rules)
typeenumservice · physical · digital · subscription
statusenumactive or archived
skustringOptional stock-keeping unit identifier
currencystringISO 4217 currency for this product’s base price
metadataobjectArbitrary key-value pairs
created_atISO 8601Creation timestamp

Budget Management

Configure monthly spending limits and alert thresholds for API usage. When the monthly limit is reached, the API returns 402 Payment Required until the next billing cycle or the limit is raised. Requires session (cookie) authentication.

GET /api/v1/budget
Retrieve current budget settings and the month-to-date spend.
Example
curl https://salesbooth.com/api/v1/budget \ -H "Cookie: session=..."
Response
{ "error": false, "success": true, "data": { "budget": { "monthly_limit": 1000.00, "monthly_limit_cents": 100000, "alert_at_percent": [80, 100], "current_spend": 612.40, "current_spend_cents": 61240, "percent_used": 61.2 } } }
POST /api/v1/budget
Update the monthly budget limit and alert thresholds.
FieldTypeDescription
monthly_limit requirednumberMonthly spend cap in USD. Set to 0 to disable the cap.
alert_at_percentarrayPercentage thresholds that trigger email alerts (e.g. [80, 100])
Example
curl -X POST https://salesbooth.com/api/v1/budget \ -H "Cookie: session=..." \ -H "Content-Type: application/json" \ -d '{ "monthly_limit": 500.00, "alert_at_percent": [75, 90, 100] }'

USDC Payment Rail

Manage USDC prepaid balances for AI agent accounts on Base L2. Agents can fund their account via Coinbase Commerce and then spend USDC against deal credits — no Stripe required. USDC balances are separate from the standard credit system.

Required scope: billing:read (balance & transactions), billing:write (create charge, set wallet)

Network: Base L2 (Coinbase). Minimum deposit: 1 USDC.

GET /api/v1/usdc?action=balance
Get the current USDC balance and agent wallet summary.
Example
curl https://salesbooth.com/api/v1/usdc?action=balance \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
Response
{ "error": false, "success": true, "data": { "balance_usdc": 42.50, "wallet_address": "0xabc...def", "network": "base", "agent_summary": { "total_spent": 157.50, "total_deposited": 200.00 } } }
GET /api/v1/usdc?action=transactions
Retrieve paginated USDC transaction history.
ParameterTypeDescription
pageintegerPage number (default: 1)
per_pageintegerResults per page (default: 20, max: 100)
POST /api/v1/usdc?action=create-charge
Create a Coinbase Commerce charge to deposit USDC into the agent’s balance. Returns a hosted checkout URL to redirect the payer to.
FieldTypeDescription
amount requirednumberAmount in USDC to deposit (minimum: 1)
Example
curl -X POST https://salesbooth.com/api/v1/usdc?action=create-charge \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "amount": 50.00 }'
POST /api/v1/usdc?action=set-wallet
Register an on-chain wallet address for the agent account. Used for identity verification and optional direct settlement.
FieldTypeDescription
wallet_address requiredstringEVM-compatible wallet address (0x...)

Fraud Signals

Review and manage fraud detection signals. Signals are generated automatically during deal and payment events and accumulate a severity score that may trigger trust-level demotions. This API allows merchants to list, resolve, and manually trigger evaluations.

Required scope: trust:read (GET), trust:write (POST resolve/evaluate)

GET /api/v1/fraud-signals
List fraud signals with optional filtering. Returns signal severity, cumulative 24h scores, and whether demotion thresholds have been crossed.
ParameterTypeDescription
unresolvedstringShow only unresolved signals: 1 or 0
limitintegerMax results (default: 25, max: 100)
offsetintegerPagination offset
Example
curl https://salesbooth.com/api/v1/fraud-signals?unresolved=1 \ -H "Authorization: Bearer sb_test_example_key_do_not_use"
GET /api/v1/fraud-signals?action=demotions
Retrieve trust-level demotion history triggered by accumulated fraud signals.
POST /api/v1/fraud-signals?action=resolve
Mark a fraud signal as resolved after investigation. Resolved signals are excluded from future severity calculations.
FieldTypeDescription
signal_id requiredstringSignal to resolve
POST /api/v1/fraud-signals?action=evaluate
Manually trigger a fraud evaluation run. Useful after resolving signals to confirm the tenant’s risk score has improved before requesting a trust-level review.

Session Auth

JSON-based authentication for the admin panel and SPA clients. Uses secure HttpOnly cookies; not intended for API key–based integrations.

GET /api/v1/auth
Returns the current session status, authenticated user, and accessible workspaces. Returns authenticated: false if no active session.
POST /api/v1/auth
Authenticate with email and password. Sets a session cookie on success. Use action=select-tenant to switch to a specific workspace after login.
FieldTypeDescription
email requiredstringUser email address
password requiredstringUser password
rememberbooleanPersist session across browser restarts (30-day remember-me cookie)
Example
curl -X POST https://salesbooth.com/api/v1/auth \ -H "Content-Type: application/json" \ -c cookies.txt \ -d '{"email": "user@example.com", "password": "secret"}'
DELETE /api/v1/auth
Logout: destroy the current session and clear the session cookie. Returns 200 OK even if no active session exists.

User Profile

Manage the authenticated user’s personal profile fields. Requires an active session.

GET /api/v1/profile
Retrieve the current user’s profile: first name, last name, email, and phone.
Response (200)
{ "error": false, "data": { "first_name": "Jane", "last_name": "Smith", "email": "jane@example.com", "phone": "+1-555-0100" } }
PATCH /api/v1/profile
Update the current user’s profile. Send only the fields to change.
FieldTypeDescription
first_namestringFirst name
last_namestringLast name
phonestringMobile phone number
POST /api/v1/profile?action=change-password
Change the current user’s password. Requires an active session. The current password must be provided for verification.
FieldTypeDescription
old_password requiredstringThe user’s current password for verification
new_password requiredstringThe new password (minimum 8 characters)
Example
curl -X POST "https://salesbooth.com/api/v1/profile?action=change-password" \ -H "Cookie: session=..." \ -H "Content-Type: application/json" \ -d '{ "old_password": "oldPassword123", "new_password": "newSecurePassword456" }'

Preferences

Store user and workspace-level UI preferences. Preferences are keyed by scope: user (global per user) or tenant (per workspace).

GET /api/v1/preferences?scope={user|tenant}
Retrieve preferences for the given scope. user scope returns global preferences (language, theme). tenant scope returns workspace preferences (recommendations_dismissed).
PATCH /api/v1/preferences?scope={user|tenant}
Update preferences for the given scope. Only whitelisted keys are accepted: language, theme for user scope; recommendations_dismissed for tenant scope.
Example
curl -X PATCH https://salesbooth.com/api/v1/preferences?scope=user \ -H "Content-Type: application/json" \ -d '{"language": "en", "theme": "dark"}'

Display Mode

Control whether the app renders in PWA standalone mode or standard browser mode. Called automatically by the front-end on load; you can also set it explicitly for testing.

GET /api/v1/display-mode
Returns the current display mode setting: standalone, browser, or auto.
POST /api/v1/display-mode
Set the display mode. Use auto to clear any forced mode and return to browser-detection.
FieldTypeDescription
mode requiredstringstandalone, browser, or auto

Business Profile

The business profile provides a natural-language description of the tenant’s business, used as context for AI website generation. Stored in tenant_settings.

GET /api/v1/business-profile
Retrieve the current business profile for the authenticated workspace.
POST /api/v1/business-profile
Save or update the business profile. The profile is a free-form description used by AI website generation and other AI features.
FieldTypeDescription
business_namestringTrading name
descriptionstringDetailed description of the business, products, and target market
industrystringIndustry category
target_marketstringIntended customer segment

Analytics Settings

Manage analytics and session replay tracking preferences for the current workspace. Settings are stored in tenants.metadata.

GET /api/v1/analytics-settings
Returns the current analytics tracking configuration including toggles for mouse recording, heatmaps, and custom CSS block selectors to exclude from recording.
PATCH /api/v1/analytics-settings
Update analytics settings. Send only the fields to change.
FieldTypeDescription
enabledbooleanMaster toggle for analytics collection
record_mousebooleanRecord mouse movements in session replays
block_selectorstringCSS selector for elements to exclude from recording (e.g. .pii-field)

Tenant Settings

Read and update workspace-level settings: business details, branding, and operational configuration. Direct column fields are stored in the tenants table; extended fields (industry, tax_id, primary_color, currency) are stored in tenants.metadata.

GET /api/v1/tenant-settings
Returns all settings for the current workspace including name, subdomain, industry, default currency, branding colours, and tax configuration.
PATCH /api/v1/tenant-settings
Update workspace settings. Send only the fields to change.
FieldTypeDescription
namestringWorkspace display name
industrystringIndustry category
default_currencystringISO 4217 code (e.g. USD)
primary_colorstringBrand colour hex (e.g. #635bff)
default_tax_ratestringDefault tax rate as decimal (e.g. 0.10 for 10%)
custom_domainstringCustom domain for the hosted website

Communication Channels

Manage the tenant’s outbound communication settings: phone number (Twilio), sender email address, and sender name. Used when sending deal notifications and quotes.

GET /api/v1/channels
Returns the current channel configuration: phone number, from email, and sender name.
POST /api/v1/channels
Save communication channel settings.
FieldTypeDescription
phone_numberstringTwilio phone number in E.164 format (e.g. +15550001234)
from_emailstringSender email address for outbound messages
from_namestringSender display name

Switch Workspace

Switch the active workspace for the current session. Users with access to multiple workspaces can switch without re-authenticating.

POST /api/v1/switch-tenant
Switch the session to a different workspace. The user must already have access to the target workspace.
FieldTypeDescription
tenant_id requiredstringTarget workspace ID

Tenant Context

Manage per-tab workspace context. Allows each browser tab to operate in a different workspace without affecting other tabs. Context is stored in the session keyed by tab ID (sent via X-Tab-ID header).

GET /api/v1/tenant-context
Returns the workspace ID associated with the current tab. Requires the X-Tab-ID header.
POST /api/v1/tenant-context
Set or clear the workspace context for a specific tab. Pass tenant_id: null to clear the tab-specific context and fall back to the session default.
FieldTypeDescription
tab_id requiredstringBrowser tab identifier
tenant_idstring|nullWorkspace ID to bind to this tab, or null to clear

Workspace List

Returns all workspaces accessible to the authenticated user. Multi-workspace users use this to populate the workspace switcher.

GET /api/v1/tenants
Returns an array of workspace objects: ID, name, slug, logo, region, regional endpoint, sandbox flag, current flag, and the user’s role in each.
Response (200)
{ "error": false, "data": [ { "tenant_id": "au_tenant_abc123", "name": "Acme Corp", "slug": "acme-corp", "logo_url": null, "role": "owner", "is_current": true, "is_sandbox": false, "region": "au", "regional_endpoint": "https://api-au.salesbooth.com" } ] }

Health Check

Public endpoint for monitoring and infrastructure probes. No authentication required. Rate limited to 10 requests per minute per IP.

GET /api/v1/health
Full health report including database, cache, and queue status. Always returns HTTP 200 — check status in the body.
ParameterDescription
typeliveness — minimal PHP-FPM alive check (use for Nginx upstream); readiness — all dependencies healthy (use for load balancer routing); omit for full report
Response (200)
{ "status": "healthy", "checks": { "database": { "status": "ok", "latency_ms": 2 }, "redis": { "status": "ok" }, "queue": { "status": "ok", "pending": 0 } }, "timestamp": "2026-03-18T10:00:00Z" }

Usage Reporting

Access AI service usage logs and cost summaries for the current workspace. Useful for cost allocation, auditing, and charting monthly spend trends.

GET /api/v1/usage?action=logs
Paginated log of API service calls with per-entry cost and token counts.
ParameterDescription
serviceFilter by service name (e.g. claude, openai)
start_dateISO 8601 start date
end_dateISO 8601 end date
limitMax results (default: 100, max: 1000)
offsetPagination offset
GET /api/v1/usage?action=summary
Monthly usage summary: total cost, token counts, and breakdown by service.
GET /api/v1/usage?action=daily
Daily usage breakdown for charting — returns an array of {date, cost, tokens} objects for the last 30 days.

Cache Administration

Inspect and flush the Redis cache for the current workspace. Requires the admin scope. Cache keys are namespaced by sb:{tenant_id}: to prevent cross-tenant access.

GET /api/v1/cache
Returns cache statistics: key count, memory usage, hit/miss ratio, and Redis version.
DELETE /api/v1/cache
Flush all cache entries for this workspace. Use the prefix parameter to invalidate only a subset.
ParameterDescription
prefixCache key prefix to invalidate (e.g. products). Omit to flush all workspace keys.

Encryption Key Rotation

Admin endpoint to check and trigger encryption key rotation for the current workspace. Re-encrypts all customer PII records using the current HKDF-derived tenant key. Requires the admin scope.

GET /api/v1/encryption-rotation
Get rotation status: number of records using legacy encryption, migration progress, and current key version.
GET /api/v1/encryption-rotation?action=rekey-status
Check the status of a background re-key job: progress percentage, records remaining, and estimated completion time.
POST /api/v1/encryption-rotation?action=start
Start or resume an encryption key rotation. Processes records in batches; safe to call multiple times. Use action=resume with a rotation ID to resume a specific paused rotation.

Deal Participants

Manage multi-party deal collaboration. Participants are agents or humans invited to a deal with specific roles, permission scopes, and revenue-share allocations. Supported roles: primary_agent, co_agent, observer.

GET /api/v1/deal-participants?deal_id={id}
List all participants for a deal. Use action=settlements to retrieve final revenue-share settlement records.
ParameterDescription
deal_id requiredDeal identifier
actionsettlements — return settlement records for a completed deal
POST /api/v1/deal-participants?deal_id={id}
Invite a participant, or perform lifecycle actions (accept, complete). Send X-Delegation-ID header if acting on behalf of an agent.
FieldTypeDescription
agent_idstringAgent identifier to invite
role requiredstringprimary_agent, co_agent, or observer
revenue_sharenumberRevenue share percentage (0–100)
scopestring[]Permission scopes granted to this participant
Example
curl -X POST "https://salesbooth.com/api/v1/deal-participants?deal_id=deal_abc" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "agent_xyz", "role": "co_agent", "revenue_share": 25, "scope": ["deals:read", "agent:negotiate"] }'
PATCH /api/v1/deal-participants?id={participant_id}
Update a participant’s role, scope, or revenue-share allocation.
DELETE /api/v1/deal-participants?id={participant_id}
Remove (withdraw) a participant from a deal. Only possible while the deal is in draft or in_progress status.

Negotiations Dashboard

Internal merchant-facing endpoint providing an aggregated view of active negotiations, auto-accept thresholds, and deal management actions. Requires an active session.

GET /api/v1/negotiations-dashboard
Returns dashboard stats and a list of active negotiations with latest proposals.
ParameterDescription
viewdashboard (default) — stats + list; detail — single deal negotiation detail (requires deal_id)
deal_idDeal ID when view=detail
POST /api/v1/negotiations-dashboard?action={action}
Perform a negotiation action. Supported actions: accept, counter, reject, update_threshold.
ParameterDescription
action requiredaccept — accept latest proposal; counter — send counter-offer; reject — reject; update_threshold — set auto-accept percentage

Dashboard Statistics

Consolidated endpoint returning all dashboard data in a single request. Cached for 2 minutes. Requires deals:read scope.

GET /api/v1/dashboard-stats
Returns entity counts, pipeline analytics, revenue time-series (last 30 days), and attention items (expiring deals, stale deals, expiring contracts).
Response (200)
{ "error": false, "data": { "counts": { "customers": 142, "deals": 38, "products": 24, "contracts": 17 }, "pipeline": { "total_value": 285000, "avg_deal_size": 7500, "win_rate": 0.68 }, "revenue_series": [{ "date": "2026-03-01", "total": 12400, "count": 3 }], "attention": { "expiring_deals": [], "expiring_contracts": [], "stale_deals": [] } } }

Site Blocks

Manage reusable content blocks for the website builder. Blocks can be shared across pages within a site and referenced by slug. Requires session authentication.

GET /api/v1/site-blocks
List all blocks for the workspace, optionally filtered by site.
ParameterDescription
site_idFilter blocks by site
idRetrieve a single block by ID
POST /api/v1/site-blocks
Create a new block, or use action=update_status to publish/unpublish a block.
FieldTypeDescription
site_id requiredstringParent site identifier
name requiredstringBlock display name
typestringBlock type (e.g. hero, testimonial, cta)
contentstringHTML or structured content for the block
PATCH /api/v1/site-blocks?id={block_id}
Update a block’s name, type, or content.
DELETE /api/v1/site-blocks?id={block_id}
Permanently delete a block. Returns 409 if the block is still referenced by active pages.

AI Website Generation

Generate full websites, page templates, or individual pages using AI. Uses the tenant’s business profile and product catalog as context. Long-running — set client timeouts to at least 120 seconds.

POST /api/v1/ai-website
Generate a complete multi-page website based on the business profile and product catalog. Creates pages in the active site.
ParameterDescription
actiontemplate — generate CSS, header, and footer only; page — generate or regenerate a single page; omit for full site generation

Domain Availability

Check whether a domain name is available for registration. Powered by the Dreamscape API.

POST /api/v1/domain-check
Check domain availability and get a registration price if available.
FieldTypeDescription
domain requiredstringDomain name to check (e.g. example.com)
Response (200)
{ "error": false, "data": { "available": true, "price": "12.99" } }
GET /api/v1/domain-check?action=server_ip
Get the server IP address for DNS A-record configuration when setting up a custom domain.
Response (200)
{ "error": false, "data": { "ip": "203.0.113.42" } }

Domain Registration

Register a domain name and associate it with the current workspace’s website. Charges are applied to the workspace credit balance.

POST /api/v1/domain-register
Register the domain and configure DNS to point to the workspace website. Requires available credits.
FieldTypeDescription
domain requiredstringDomain to register (must be verified as available first)
site_idstringSite to associate the domain with

Activity Stream (SSE)

Real-time activity feed using Server-Sent Events. Polls the activity_feed table every 2 seconds and streams new events to the client. Use the browser’s EventSource API for automatic reconnection.

GET /api/v1/activity-stream
Opens a persistent SSE connection. Events are sent as JSON with id, event type, and data fields. The connection emits a heartbeat event every 30 seconds.
ParameterDescription
last_event_idResume from this event ID (also read from Last-Event-ID header on reconnect)
Example (JavaScript)
const es = new EventSource('/api/v1/activity-stream'); es.addEventListener('activity', e => { const event = JSON.parse(e.data); console.log(event.type, event.entity_id); }); es.addEventListener('heartbeat', () => console.log('alive'));

Session Replays

Manage recorded session replay data. Replay events are collected via the Event Collection endpoint and stored as JSONL files. Use the Analytics Settings endpoint to configure recording preferences.

DELETE /api/v1/replays?session_id={id}
Permanently delete a session recording from the database and disk. Returns 404 if the session is not found or does not belong to the current workspace.
ParameterDescription
session_id requiredSession replay identifier

Event Collection

Public endpoint that accepts session replay and analytics events from the SDK. No authentication required — uses a publishable key for workspace routing. Called automatically by the analytics SDK.

POST /api/v1/collect
Store a batch of session replay or analytics events. Events are stored as JSONL organised by domain and session ID.
FieldTypeDescription
session_id requiredstringUnique session identifier (generated client-side)
events requiredarrayArray of event objects with type, timestamp, and data
publishable_key requiredstringWorkspace publishable key for routing

Job Queue

Monitor and manage the background job queue. Supports inspecting queue statistics, checking individual job status, viewing dead-lettered jobs, retrying failed jobs, and purging old records. Requires queue:read or queue:write scope.

GET /api/v1/queue
Get queue statistics: pending, processing, completed, and dead-lettered job counts.
GET /api/v1/queue?action=status&job_id={id}
Get detailed status for a specific job: state, attempts, last error, and timestamps.
GET /api/v1/queue?action=dead-letter
List dead-lettered (permanently failed) jobs. Returns up to 100 entries per page.
POST /api/v1/queue?action=retry&job_id={id}
Re-enqueue a dead-lettered job. Requires queue:write scope.
POST /api/v1/queue?action=purge
Purge old completed or dead-lettered jobs. Use action=purge-dead-letter to purge only the dead letter queue.

Agent Registry

Same-tenant agent peer discovery for multi-agent coordination. Enables agents to discover peer and child agents in the same workspace, query activity summaries, and detect product contention before starting duplicate negotiations. Requires agent:discover scope.

Privacy: Responses are summary-level only to prevent information leakage between competing agents. Agents may only see their peers and children — never ancestors in the delegation hierarchy.

GET /api/v1/agent-registry
Discover active agents or check for product contention.
ParameterDescription
action requiredlist_agents — list active peer agents; agent_activity — activity summary for an agent; check_contention — check if a product is already being negotiated
product_idProduct ID to check for contention (when action=check_contention)
agent_idAgent ID to query activity for (when action=agent_activity)

AI Chat Assistant

Conversational AI assistant for managing customers, products, deals, and viewing business data. Supports streaming responses. Powered by Claude with extended thinking for complex queries.

POST /api/v1/chat
Send a message to the AI assistant. Supports streaming via Server-Sent Events when stream=true.
FieldTypeDescription
messages requiredarrayChat history: array of {role: "user"|"assistant", content: string}
streambooleanEnable SSE streaming (default: false)
thinkingbooleanEnable extended thinking for complex queries (default: false)

Text to Speech

Convert text to natural-sounding speech using OpenAI TTS. Supports streaming audio for low-latency playback. Requires a configured OpenAI API key.

POST /api/v1/tts
Convert text to MP3 audio. Use stream=true for raw audio streaming (faster); the default returns base64-encoded audio in JSON.
FieldTypeDescription
text requiredstringText to convert (max 4096 characters)
voicestringVoice: nova (default), alloy, echo, fable, onyx, shimmer
streambooleanStream raw MP3 bytes directly (sets Content-Type: audio/mpeg)

Realtime Voice Session

Create ephemeral tokens for browser-side WebSocket connections to the OpenAI Realtime API. Keeps the OpenAI API key secure on the server. Tokens expire after 60 seconds.

POST /api/v1/realtime-session
Returns a short-lived ephemeral token for the client to connect directly to OpenAI’s Realtime API WebSocket.
FieldTypeDescription
modelstringOpenAI Realtime model (default: gpt-4o-realtime-preview)
voicestringTTS voice for the realtime session (default: nova)
Response (200)
{ "error": false, "data": { "client_secret": { "value": "ek_...", "expires_at": 1742000060 }, "session_id": "sess_abc123" } }

Realtime Function Calls

Execute function calls originating from the OpenAI Realtime API voice assistant. The browser forwards function call requests here; the server executes them using full service-layer access and returns results.

POST /api/v1/realtime-function
Execute a named function call. Supported functions include customer search, deal listing, product lookup, contract status, and more — matching the same tool surface as the chat assistant.
FieldTypeDescription
function_name requiredstringName of the function to execute (e.g. search_customers, get_deal)
arguments requiredobjectFunction arguments as a JSON object

Realtime Usage Reporting

Client-side token usage reporting for Realtime API voice sessions. Because the browser connects directly to OpenAI via WebSocket, the server cannot observe usage; the client reports it here for billing and analytics tracking.

POST /api/v1/realtime-usage
Record token usage from a completed realtime voice session.
FieldTypeDescription
session_id requiredstringRealtime session identifier
input_tokensintegerNumber of input tokens consumed
output_tokensintegerNumber of output tokens generated
duration_secondsnumberSession duration in seconds

CSV Import

Three-step CSV import wizard for bulk-loading customers and products. Step 1 parses the file and auto-detects column mappings. Step 2 validates the mapped data and returns row-level errors. Step 3 executes the import inside a database transaction.

POST /api/v1/import?action=parse
Parse a CSV file (multipart/form-data upload). Returns detected headers, sample rows, and auto-suggested column mappings.
FieldTypeDescription
file requiredfileCSV file to import (multipart upload)
entity requiredstringcustomers or products
POST /api/v1/import?action=validate
Validate column-mapped data. Returns per-row errors without making any changes.
POST /api/v1/import?action=import
Execute the import inside a transaction. Returns counts of created, updated, and skipped records.

Saved Configs Admin

Admin-side management of widget saved configurations (product configurations saved by buyers before checkout). Supports listing with search/filter/sort, analytics, conversion to deals, and deletion. Requires deals:read scope.

GET /api/v1/saved-configs-admin
List saved configurations with optional search, filter by product, and sort. Also supports action=stats and action=analytics&period=30 for conversion funnel analytics.
POST /api/v1/saved-configs-admin?id={id}&action=convert
Convert a saved configuration into a deal. Creates the deal, adds the configured product as a line item, and optionally creates a customer record. Requires deals:write scope.
PATCH /api/v1/saved-configs-admin?id={id}
Update a saved configuration by numeric ID. Allows updating the customer name, email, or option selections without converting to a deal. Requires deals:write scope.
FieldTypeDescription
customer_namestringUpdate the saved customer name (set to empty string to clear)
customer_emailstringUpdate the customer email address (must be valid email format)
option_selectionsobjectUpdated option selections keyed by product ID (set to null to clear)
Example
curl -X PATCH "https://salesbooth.com/api/v1/saved-configs-admin?id=42" \ -H "Authorization: Bearer sb_test_example_key_do_not_use" \ -H "Content-Type: application/json" \ -d '{ "customer_email": "updated@example.com", "customer_name": "Jane Smith" }'
Response (200)
{ "error": false, "data": { "updated": true, "id": 42 } }
DELETE /api/v1/saved-configs-admin?id={id}
Delete a saved configuration. Requires deals:write scope.

Sandbox Toggle

Switch the dashboard between live mode and sandbox (test) mode. Only available for session-authenticated users — API key requests cannot change the sandbox mode. Sandbox mode uses Stripe’s test keys and does not process real payments.

GET /api/v1/sandbox-toggle
Returns the current mode: test (sandbox active) or live.
POST /api/v1/sandbox-toggle
Switch between sandbox and live mode.
FieldTypeDescription
mode requiredstringtest for sandbox, live for production

Payment Intent

Create a Stripe PaymentIntent for a deal’s deposit or full amount. Called by the <salesbooth-deal> embed widget when the buyer reaches the payment step. Requires deals:write scope.

POST /api/v1/payment-intent
Create a Stripe PaymentIntent. Returns a client_secret for use with Stripe.js to complete payment on the client.
FieldTypeDescription
deal_id requiredstringDeal to create a PaymentIntent for
amountnumberOverride amount in the deal’s currency (omit to use deal total)
Response (200)
{ "error": false, "data": { "client_secret": "pi_xxx_secret_yyy", "amount": 149900, "currency": "usd" } }

Onboarding

Complete the new-user onboarding wizard or create an additional workspace for an existing user. No authentication required for new users; existing users must be authenticated.

POST /api/v1/onboarding
Complete onboarding: creates the user account, tenant workspace, and initial products in a single transaction. Returns a session cookie for immediate login.
FieldTypeDescription
first_name requiredstringUser first name
last_name requiredstringUser last name
email requiredstringUser email address
password requiredstringPassword (min 8 characters)
business_namestringBusiness or workspace name (required for human accounts)
industrystringBusiness industry (required for human accounts)
servicesarrayList of services offered (required for human accounts). Each item: {name, description, price_min, price_max}
deposit_percentagenumberDefault deposit percentage (0–100)
phonestringBusiness phone number
websitestringBusiness website URL
countrystringTwo-letter country code (default: US)
regionstringData residency region: au, eu, or us
account_typestringAccount type: human (default) or agent. Agent accounts skip business field validation.
POST /api/v1/onboarding?mode=new-workspace
Create an additional workspace for an already-authenticated user. The new workspace is automatically linked to the user’s account.

Credential Verification

Public endpoint for verifying the signature and status of Salesbooth verifiable credentials. No authentication required — any third party (lenders, insurers, regulators, counterparties) can verify a credential’s authenticity.

POST /api/v1/verify
Verify a credential: checks the Ed25519 signature, revocation status, and expiry. Returns valid: true if the credential is authentic and has not been revoked.
FieldTypeDescription
credential requiredobjectThe verifiable credential JSON object (as issued by Salesbooth)
Response (200)
{ "error": false, "data": { "valid": true, "credential_id": "vc_abc123", "deal_id": "deal_xyz", "issued_at": "2026-03-01T10:00:00Z", "expires_at": "2027-03-01T10:00:00Z", "revoked": false } }

System Admin

System-level administration endpoints. Requires is_system_admin = true on the user account. These endpoints are not accessible to regular tenant users.

System Admin Only: All /system-admin endpoints enforce a system-admin check. Regular API keys and tenant users will receive 403 Forbidden.

GET /api/v1/system-admin?action={action}
Retrieve system-level data. Supported actions:
ActionDescription
statsSystem-wide statistics: total tenants, active users, deal volume
tenantsList all tenants with pagination
tenantGet a specific tenant’s detail (requires id param)
settingsGet all system-level settings
credit-ledgerGet credit ledger for a specific tenant (requires id param)
POST /api/v1/system-admin?action={action}
Perform system-level actions:
ActionDescription
impersonateStart impersonating a tenant (for support)
stop-impersonateEnd impersonation and restore system admin session
settingsSave a system-level setting
grant-creditsGrant free credits to a tenant
rotate-keysTrigger encryption key rotation for a specific tenant

Internal Endpoints

The following endpoints are infrastructure-facing or webhook receivers. They are listed here for completeness but are not intended for direct use by API consumers. Do not call these endpoints from client integrations.

GET /api/v1/api
API discovery endpoint. Returns a list of available API routes, authentication methods, agent integration details, and a link to the OpenAPI specification. No authentication required. Not required for normal integration — use the OpenAPI spec instead.
Example
curl https://salesbooth.com/api/v1/api
Response (200)
{ "error": false, "data": { "name": "Salesbooth API", "version": "1.0.0", "base_url": "https://salesbooth.com/api/v1", "documentation": "https://salesbooth.com/docs", "openapi_spec": "https://salesbooth.com/api/openapi.json", "endpoints": { "deals": { ... }, "customers": { ... } } } }
POST /api/v1/csp-report
Receives browser Content Security Policy violation reports. This is the target of the report-uri CSP directive sent in all page responses. No authentication required. Accepts both application/csp-report and application/json content types. Rate limited at 30 req/min per IP.
Request body (browser-sent automatically)
{ "csp-report": { "document-uri": "https://salesbooth.com/deals", "violated-directive": "script-src", "blocked-uri": "https://evil.example.com/script.js" } }
POST /api/v1/email-webhook
Receives inbound email events from SendGrid or Mailgun (bounces, complaints, delivery confirmations, and inbound messages). Validated via a provider-specific token. No authentication required — configure your email provider to POST events to this URL.
Configure in your email provider
Webhook URL: https://salesbooth.com/api/v1/email-webhook Content-Type: multipart/form-data (SendGrid) or application/json (Mailgun)
POST /api/v1/stripe-webhook
Receives and processes incoming Stripe webhook events: payment intents, subscription lifecycle, invoice events, and dispute notifications. Signature-verified via the Stripe-Signature header against STRIPE_WEBHOOK_SECRET. No authentication required — configure in your Stripe dashboard.
HeaderDescription
Stripe-Signature requiredStripe-provided HMAC signature for payload verification
Configure in Stripe Dashboard
Webhook URL: https://salesbooth.com/api/v1/stripe-webhook Events: payment_intent.*, invoice.*, customer.subscription.*, charge.dispute.*
GET /api/v1/twilio
Returns Twilio configuration status and communication history. No credentials are exposed. Requires session authentication.
ParameterDescription
actionsettings (default) for configuration status; history for communication history log
POST /api/v1/twilio
Save Twilio credentials or send an outbound SMS, voice call, or email. Called by the Salesbooth dashboard communications settings page. Requires session authentication.
FieldDescription
action requiredsettings to save credentials; sms to send SMS; call to initiate voice call; email to send email
toRecipient phone number (E.164 format) or email address, depending on action
messageMessage body for SMS or email content
account_sidTwilio account SID (required for action=settings)
auth_tokenTwilio auth token (required for action=settings)
POST /api/v1/twilio-webhook
Receives inbound SMS messages, voice call status callbacks, and delivery status updates from Twilio. Signature-verified via Twilio’s X-Twilio-Signature header. No authentication required — configure in your Twilio console.
ParameterDescription
typeEvent type: sms (inbound message), voice (call status), status (delivery callback)
Configure in Twilio Console
SMS Webhook URL: https://salesbooth.com/api/v1/twilio-webhook?type=sms Voice Webhook URL: https://salesbooth.com/api/v1/twilio-webhook?type=voice

Changelog

2026-03-2413 missing endpoints documented; subscription status enum corrected (#1209)

Documentation gap-fill pass resolving all endpoints present in openapi.json but missing from the docs:

  • Federation — Added GET /federation/negotiate and POST /federation/negotiate endpoint cards with parameter tables and examples
  • Playground API — New #playground-api section documenting POST /playground/session (create ephemeral key) and GET /playground/session (check validity) with full response examples
  • Widget Config — Corrected embed-code path to GET /widget-config/embed-code to match OpenAPI spec
  • Saved Configs Admin — Added missing PATCH /saved-configs-admin?id={id} endpoint card documenting customer_name, customer_email, and option_selections fields
  • Internal Endpoints — Upgraded summary table to full endpoint cards for GET /api, POST /csp-report, POST /email-webhook, POST /stripe-webhook, GET /twilio, POST /twilio, and POST /twilio-webhook
  • Subscriptions — Corrected GET /subscriptions status filter enum: expired replaced with past_due to match the actual API and state machine

2026-03-1847 missing API resource groups documented (#792)

Comprehensive documentation pass covering all previously undocumented API endpoints:

  • Auth & Session/auth (GET/POST/DELETE), /profile, /preferences, /display-mode
  • Workspace Settings/business-profile, /analytics-settings, /tenant-settings, /channels, /switch-tenant, /tenant-context, /tenants
  • Monitoring/health (public, with liveness/readiness probes), /cache, /usage, /dashboard-stats, /encryption-rotation
  • Deal Management/deal-participants (multi-party CRUD + settlements), /negotiations-dashboard
  • Website Builder/site-blocks (CRUD), /ai-website, /domain-check, /domain-register
  • Platform/activity-stream (SSE), /replays, /collect, /queue (dead-letter + retry)
  • AI Voice & Chat/chat, /tts, /realtime-session, /realtime-function, /realtime-usage
  • Agent Registry/agent-registry (peer discovery + contention detection)
  • Developer Tools/import (CSV wizard), /saved-configs-admin, /sandbox-toggle, /payment-intent
  • Onboarding & Verification/onboarding (new user + new workspace), /verify (public credential verification)
  • System Admin/system-admin (stats, impersonation, grants)
  • Internal Endpoints/csp-report, /stripe-webhook, /email-webhook, /twilio-webhook, /twilio, /api listed as Internal

2026-03-1522 missing public endpoints documented

Comprehensive documentation additions for previously undocumented public APIs:

  • Customer Portal — Full authentication flow (/customer-auth) and buyer self-service portal (/customer-portal): deals, contracts, signing, payment, and profile management.
  • Deal Discovery — Agent-facing deal discovery REST API (/deal-discovery) with filtering and schema access. Complements the existing MCP discover_deals tool.
  • Quotes & Invoices/quotes with generate, retrieve by short code, and list actions.
  • Deal Notifications/deal-notifications for sending quote, invoice, and reminder notifications via the customer’s preferred channel.
  • Pricing Simulation/simulate-pricing: bundle simulation, scenario comparison, and negotiation history analytics.
  • Real-Time Events (SSE)/events/stream Server-Sent Events endpoint with reconnect, heartbeat, and per-event HMAC signatures.
  • Widget A/B Tests/ab-tests full CRUD plus promote and the public resolve endpoint called on every widget load.
  • Widget Public Endpoints/widget-intelligence (popularity & smart defaults), /widget-contract (generate + sign), /widget-discount (promo code validation), /widget-validate (configuration compatibility check), and /widget-payment-preview (full payment breakdown for headless carts).
  • FX Rates — Unauthenticated /fx-rate endpoint for multi-currency price display.
  • Machine-Readable Schemas/schema/state-machine and /schema/deal-terms for programmatic agent integration.
  • Availability — Booking slot availability checking via publishable key.
  • Federation Discovery — Public /federation/discovery manifest endpoint for cross-instance federation handshakes.
  • Budget Management/budget GET/POST for monthly spend caps and alert thresholds.
  • USDC Payment Rail/usdc balance, transactions, Coinbase charge creation, and wallet registration.
  • Fraud Signals/fraud-signals list, demotion history, resolve, and manual evaluation.

2026-03-12Documentation completeness update

Comprehensive documentation additions for previously undocumented APIs:

  • Intelligence API — All 13 endpoint types now documented with full parameter tables, response schemas, scoring weight explanations, risk factor definitions, and SDK examples. Added: score, risk, close_forecast, pipeline_forecast, win_probability_curve, score_history, score_accuracy.
  • Negotiations — Added lifecycle state machine diagram, suggest action with AI counter-offer strategies, intelligence endpoint for negotiations, and full parameter/response docs for all actions.
  • Delegations — Added chain depth rules, spending cap cascade explanation, proposal flow (propose/accept/reject/counter), and X-Delegation-ID usage pattern.
  • Subscriptions — Added lifecycle state machine with all 5 states, renew, retry-payment, change, and usage_summary endpoints.
  • Webhook Payloads — Added 10 additional payload schemas: contract.signed, negotiation.proposed, negotiation.countered, negotiation.accepted, subscription.created, subscription.past_due, subscription.renewed, subscription.cancelled, escrow.created. Enhanced signature verification with timestamp replay prevention.
  • SDK Quick Start — Added 5 new runnable examples: Intelligence API, Negotiations, Webhook Listener, Product/Deal flow with discount.
  • Rate Limiting — Full three-tier documentation: per-key trust-level multipliers (L0–L4), per-IP limits, global circuit breaker, all response headers, and retry pattern.

2026-03-05Deprecate query parameter authentication

Passing API keys via the ?api_key= query parameter is now deprecated. Requests using this method will receive an X-Deprecation-Warning response header. Migrate to the Authorization: Bearer header or X-API-Key header.

Tenants can opt in to immediate enforcement by setting enforce_header_auth to 1 in tenant settings, which will reject query parameter authentication with 400 Bad Request.

The Node.js SDK already uses header-based authentication — no SDK changes are required.

© 2026 Salesbooth. OpenAPI Spec