SalesPutty native API
Version 1. One monthly bill for new self-service selections, with independent usage pools. Native spe_ keys cannot access super-admin features, agency vendor vaults or another account's data. Private prompts and engine code are never part of these responses.
Access & billing
Base URL: https://salesputty.com/api/public/engines/v1
Create a native key in the dashboard. Send Authorization: Bearer spe_… on every call. Keys are shown once, stored hashed, checked for revocation and active Stripe billing on every request. New accounts use Solo ($29/month), Agency ($99/month) or Agency Ultra ($499/month) platform access, with a first free calendar month and no card. Register an app in /build, activate an API, and create its connected native key. Agency APIs each have a seven-day card-required first trial. Solo APIs have no trial. New selections share one monthly invoice with the platform. Additions start immediately; paid partial-month charges are deferred to the next shared invoice. Plan changes apply at renewal. Activating billing requires explicit approval of the platform and selected tools. API trial allowances remain product-specific. Legacy customers keep their original billing rules.
POST generation and data calls require an Idempotency-Key of 8 to 120 characters. Reuse the same key only for the identical request. Successful replay does not consume another credit. Throughput ceilings follow your plan: Starter 60 calls a minute and 6 in parallel, Growth 120 and 8 and Agency Ultra 600 and 24. Monthly limits stop requests, not automatic paid overages. Usage consumes your prepaid monthly allowance; it is not a separate Stripe charge for each HTTP request. Workspace setup, request-status reads and outcome reporting are unmetered administrative calls. Successful generation and data operations are stored in the usage ledger; retries reuse the saved result without another charge. CRM/database imports max 500 records/request; reads return 100/page; custom data max 20 bounded values.
Build a custom CRM from intake
POST /data. One CRM AI action. Returns a CRM ID and a custom layout with pipeline stages and typed fields. Subsequent record calls use that crm_id.
curl -X POST https://salesputty.com/api/public/engines/v1/data \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"product": "crm",
"operation": "build_crm",
"name": "Acme SaaS",
"intake": "B2B finance software in US and Canada. Track demos, trials and annual contracts. Include seats and annual contract value."
}'Store & filter cold contacts
POST /data. Select product crm or database. CRM requires crm_id; database stores your account's independent cold-contact list. AI filters compile plain English into company/title/country/stage filters, never raw SQL or invented contact facts.
curl -X POST https://salesputty.com/api/public/engines/v1/data \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"product": "database",
"operation": "add_records",
"records": [
{
"email": "jane@example.com",
"name": "Jane",
"company": "Example",
"title": "Sales Director",
"country": "US",
"stage": "new",
"data": {
"industry": "software"
}
}
]
}'curl -X POST https://salesputty.com/api/public/engines/v1/data \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"product": "database",
"operation": "ai_filter",
"prompt": "Sales directors at software companies in Canada",
"page": 0
}'Other operations: list_records (filter, page), update_record (record_id, stage), delete_record (record_id), list_crms. add_records counts one data call per batch, not per row. AI filter and CRM build count one AI action each. Stored records are capped independently of monthly calls.
CRM team membership
Only your agency's API credential may manage memberships in a CRM it owns. admin and rep are client CRM roles only, never platform administration. Your app must enforce each user's CRM membership and role before proxying API requests; never put the agency key in a public browser.
curl -X POST https://salesputty.com/api/public/engines/v1/data \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"product": "crm",
"operation": "save_member",
"crm_id": "YOUR_CRM_UUID",
"email": "rep@example.com",
"role": "rep"
}'members lists email and role. remove_member removes the named email. Unlimited invited members; membership calls consume the CRM data-call allowance.
Reply & campaign generation
First POST /workspaces with name and rules: offer, company, address, senderName, senderTitle, repEmail and b2b:true; optional tone, boundaries, handoff, availability and geography (US/CA/US_CA). GET /workspaces returns your workspace IDs. POST /generate accepts reply for replies, rotation for campaign creation, and the existing v1 compatibility identifiers ooo, winback or reverse_ooo for inbox retargeting. These identifiers remain stable; they do not expose implementation recipes.
curl -X POST https://salesputty.com/api/public/engines/v1/generate \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"workspace_id": "YOUR_WORKSPACE_UUID",
"operation": "reply",
"prospect_email": "jane@example.com",
"message": "Sounds useful, can we talk next week?",
"history": "Earlier thread messages",
"automated": false
}'Response: request_id, data (status, message, tactic, variants, return_date, alternate_email, handoff), credits_charged and reset_at. Your app sends the returned message and uses handoff.cc to loop in the client. Opt-outs are workspace-blocklisted and return no reply; deterministic suppressed requests cost zero. Inbox retargeting returns structured campaign outputs. Its internal selection and timing methods are proprietary. Rotation produces four weeks of copy, not an automatic tournament. Sending, schedules and provider purchases are never started by these APIs.
Request status & learning
GET /requests?id=REQUEST_UUID reads your request status and saved result. POST /requests with request_id and outcome (cold, lukewarm, warm, handoff) records observed reply outcomes. Subsequent replies can use your workspace's tactic/outcome history; no client messages are shared across accounts.
Status codes are endpoint-specific: generation uses 400 invalid fields, 401 invalid key, 402 subscription required, 403 access/billing verification unavailable, 404 missing owned object, 409 conflicting/pending request, 413 oversized body, 429 monthly/rate/concurrency limit and 502 incomplete generation. Data uses 400 invalid fields or JSON, 401 invalid key, 413 oversized body and 409 for access, quota, conflict or processing errors. Workspace endpoints can return 400/403; request-status endpoints can return 400/404. Failed generation is not charged to the API allowance, but may have incurred compute; do not blindly retry unknown outcomes with new keys.
Native integration recipe
// Run in YOUR server, never a public browser
const response = await fetch("https://salesputty.com/api/public/engines/v1/data", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SALESPUTTY_ENGINE_KEY}`,
"X-SalesPutty-Release": "2026-11-10",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({ product: "database", operation: "list_records", page: 0 }),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error);Compatibility & release pinning
Send X-SalesPutty-Release: 2026-11-10 to explicitly select the supported v1 release. Connected apps are pinned to that release. Unsupported release values are rejected rather than silently upgraded. Existing v1 calls without this header remain compatible. There is no newer release or upgrade preview yet. New features will be opt-in; breaking changes require a new major version with release notes and a migration recipe. Safety fixes may be applied and disclosed.
Credential boundaries
- Your customer key is a newly generated access token, not a copy, encoded bundle or export of our provider credentials. It authorizes requests to SalesPutty, not direct access to our vendor accounts.
- No endpoint exports platform provider keys, vault encryption keys, operator tokens, private prompts or internal integration documentation. Responses contain your permitted data and operation results only.
- Agency brings its own collection, verification, mailbox and sending credentials. Solo may use supported managed services without ever receiving the underlying provider credentials. Availability and separate subscriptions still apply.
- Keep the customer token in your server's secret store. Never include it in browser code, mobile bundles, public repositories, URLs, analytics, screenshots or logs. Redact Authorization headers and prospect content from operational logs.
- Create a separate connected app and key per deployment. To rotate, create a replacement, update your server, verify a read, then revoke the old key. Disconnecting an app also revokes its associated native keys. There is no recovery endpoint for the original token.
- Customer keys identify the owning account, not your individual end users. Your server must authenticate every user and authorize the target client workspace or CRM before making a request. A client CRM admin is not a SalesPutty operator.
Workspace request example
Create one workspace per campaign instruction set. Required fields and bounds: name 2–120 characters; offer 2–2,000; company and sender name/title 2–120; address 5–300; repEmail a valid email up to 254. tone, boundaries and handoff allow up to 2,000 characters, availability up to 500. b2b must be true. geography accepts US, CA or US_CA. Save the returned UUID in your server-side client mapping.
curl -X POST https://salesputty.com/api/public/engines/v1/workspaces \
-H "Authorization: Bearer $SALESPUTTY_ENGINE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-d '{
"name": "Example Software",
"rules": {
"offer": "Workflow software for B2B teams",
"company": "Example Software",
"address": "123 Example Street, Toronto, ON",
"senderName": "Alex",
"senderTitle": "Sales Director",
"repEmail": "team@example.com",
"tone": "Friendly and concise",
"boundaries": "No prices or invented evidence",
"handoff": "Confirmed interest in speaking",
"availability": "Tuesday and Thursday afternoons, Eastern time",
"geography": "US_CA",
"b2b": true
}
}'Workspace creation is a write, not an idempotent generation call. Do not automatically repeat it after a network timeout: first GET /workspaces and reconcile the returned list. Updating client rules is currently available in the dashboard, not a documented workspace-update API.
Data field reference
- Each record requires a valid email, maximum 254 characters. Optional name, company and title allow 120 characters; country is US or CA, default US; stage allows 60 characters, default new.
- data contains up to 20 custom entries. Keys allow 50 characters; values are strings up to 500 characters, numbers, booleans or null. No nested objects or arrays.
- CRM calls require crm_id except build_crm and list_crms. build_crm requires name (2–120 characters) and intake (up to 4,000). ai_filter requires prompt (up to 1,500).
- list_records accepts page, starting at 0, and filter with company, title, country and stage. Responses contain records, total, page, page_size and the applied filters. AI filtering only operates on stored records; it does not collect or enrich contacts.
- update_record currently updates stage only; it requires record_id. delete_record requires record_id. Both return an ok result. Membership operations require crm_id and, for save/remove, email. Roles are admin or rep.
- Creation returns id, name and schema. Schema contains 2–8 stages and up to 20 typed fields (text, number or boolean). add_records returns added. list_crms returns id, name and schema entries.
Remove invalid leads automatically
POST /invalid-leads with your key. Point Instantly bounce/invalid webhooks or your verification tool here. Send {"event_type":"email_bounced","lead_email":"..."}, {"email":"...","result":"invalid"} or {"emails":[...]}. Matching leads are deleted from your contact database and CRM. Free, no usage charged.
Reliable retries and handoffs
- Assign a durable Idempotency-Key before each logical /generate or /data operation. Store it together with the exact payload. Network retries use that same key and payload, not a fresh UUID.
- Persist request_id as soon as it is returned. A complete replay returns the saved result with replayed:true. Pending or failed requests must be inspected with GET /requests?id=REQUEST_UUID.
- For generation limits, honor reset_at. Data quota errors currently describe the reset in the error text. Do not assume a Retry-After header, automatic retry or automatic overage purchase.
- Only send a generated message after validating its status and your sending authorization. delivery:not_sent means generation has not delivered an email. Suppressed opt-outs and automated replies have an empty message and must not be sent.
- For a warm result, handoff supplies cc and general availability, not a booked appointment. Your app performs any sending and CRM update, then POST /requests with the observed outcome. Record real outcomes, not guessed conversions.
- Test with your own permitted data and a subscribed account. Never send test messages to prospects merely to verify connectivity. There is no separate sandbox credential or public webhook-registration API in this release.
Examples use fictional business details. Private prompts, model routing, learning recipes, provider credentials and inbox-retargeting algorithms are deliberately excluded. Supported inputs, outputs and limitations remain documented so custom builds can integrate reliably.
Release notes
2026-11-11 · Platform access: Agency and Solo account setup, independent seven-day API trials, registered connections and explicit release pinning. v1 request fields are unchanged.
2026-11-10 · v1: Independent engine subscriptions, native keys, intake-built CRM, contact storage, safe AI filters, member management, reply/campaign generation, idempotency and feature requests. New features are listed here when shipped, not promised as already live.