Scenario
Close’s Smart Views are saved lead filters (“Enterprise FinTech”, “Churned Q4”). You want to pull leads matching a Smart View and auto-generate personalized outreach content using Mavera’s Generations API, tailored to that segment.Architecture
Code
import os, requests
from requests.auth import HTTPBasicAuth
CLOSE_KEY = os.environ["CLOSE_API_KEY"]
CLOSE_AUTH = HTTPBasicAuth(CLOSE_KEY, "")
MAVERA_KEY = os.environ["MAVERA_API_KEY"]
def close_get(path, params=None):
r = requests.get(f"https://api.close.com/api/v1{path}", auth=CLOSE_AUTH, params=params or {})
r.raise_for_status()
return r.json()
# 1. List Smart Views
views = close_get("/saved_search/", {"_type": "lead"}).get("data", [])
print("Smart Views:")
for v in views:
print(f" - {v['name']} (id: {v['id']})")
target = views[0] if views else None
if not target:
print("No Smart Views found.")
exit()
# 2. Fetch matching leads
leads = close_get("/lead/", {"query": target.get("query", ""), "_limit": 50,
"_fields": "id,display_name,contacts,custom,description"}).get("data", [])
print(f"\nUsing: {target['name']} ({len(leads)} leads)")
# 3. Build segment description
companies = [l["display_name"] for l in leads[:5]]
titles = list({c["title"] for l in leads for c in l.get("contacts", []) if c.get("title")})[:5]
segment_desc = (
f"Segment: '{target['name']}'\nCompanies: {', '.join(companies)}\n"
f"Titles: {', '.join(titles)}\nCount: {len(leads)}"
)
# 4. Generate outreach content
gen = requests.post(
"https://app.mavera.io/api/v1/generations",
headers={"Authorization": f"Bearer {MAVERA_KEY}"},
json={"prompt": (
f"Write a cold email for this B2B segment. Under 150 words, soft CTA.\n\n"
f"{segment_desc}\n\n"
f"Write 3 variants: (1) Pain-point led, (2) Social proof, (3) Curiosity/question led"
)},
)
gen.raise_for_status()
print(f"\n{'='*50}\nGenerated content for: {target['name']}\n{'='*50}")
print(gen.json().get("content", gen.json().get("text", "")))
# 5. LinkedIn variant
li = requests.post(
"https://app.mavera.io/api/v1/generations",
headers={"Authorization": f"Bearer {MAVERA_KEY}"},
json={"prompt": f"Write a LinkedIn connection request (under 300 chars) for this segment.\n\n{segment_desc}"},
)
li.raise_for_status()
print(f"\nLinkedIn message:\n{li.json().get('content', li.json().get('text', ''))}")
const CLOSE_KEY = process.env.CLOSE_API_KEY;
const CLOSE_AUTH = "Basic " + Buffer.from(`${CLOSE_KEY}:`).toString("base64");
const MAVERA_KEY = process.env.MAVERA_API_KEY;
async function closeGet(path, params = {}) {
const url = new URL(`https://api.close.com/api/v1${path}`);
for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
const res = await fetch(url, { headers: { Authorization: CLOSE_AUTH } });
if (!res.ok) throw new Error(`Close ${res.status}`);
return res.json();
}
// 1. List Smart Views
const views = (await closeGet("/saved_search/", { _type: "lead" })).data || [];
console.log("Smart Views:", views.map((v) => v.name).join(", "));
const target = views[0];
if (!target) { console.log("No views."); process.exit(0); }
// 2. Fetch matching leads
const leads = (await closeGet("/lead/", {
query: target.query || "", _limit: 50, _fields: "id,display_name,contacts,custom",
})).data || [];
console.log(`\nUsing: ${target.name} (${leads.length} leads)`);
// 3. Build segment description
const companies = leads.slice(0, 5).map((l) => l.display_name);
const titles = [...new Set(leads.flatMap((l) => (l.contacts || []).map((c) => c.title).filter(Boolean)))].slice(0, 5);
const segmentDesc = `Segment: '${target.name}'\nCompanies: ${companies.join(", ")}\nTitles: ${titles.join(", ")}\nCount: ${leads.length}`;
// 4. Generate content
const genRes = await fetch("https://app.mavera.io/api/v1/generations", {
method: "POST",
headers: { Authorization: `Bearer ${MAVERA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ prompt:
`Write a cold email for this B2B segment. Under 150 words, soft CTA.\n\n${segmentDesc}\n\n` +
`3 variants: (1) Pain-point, (2) Social proof, (3) Curiosity` }),
});
const gen = await genRes.json();
console.log(`\n${"=".repeat(50)}\nGenerated for: ${target.name}\n${"=".repeat(50)}`);
console.log(gen.content || gen.text || "");
// 5. LinkedIn variant
const liRes = await fetch("https://app.mavera.io/api/v1/generations", {
method: "POST",
headers: { Authorization: `Bearer ${MAVERA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: `LinkedIn connection request (under 300 chars) for:\n\n${segmentDesc}` }),
});
console.log(`\nLinkedIn:\n${(await liRes.json()).content || ""}`);
Example Output
Using: Enterprise FinTech (34 leads)
**Variant 1 — Pain-point led:**
Subject: Your compliance team is spending 40 hours/week on reports
Hi {{first_name}}, FinTech compliance teams are drowning in manual
reporting. Our platform automates SOX and SOC 2 reports, cutting
prep time by 80%. Worth a 15-minute walkthrough this week?
**Variant 2 — Social proof:**
Subject: How Acme Payments cut audit prep from 3 weeks to 2 days
Hi {{first_name}}, Acme Payments reduced audit prep from 3 weeks
to 2 days. Happy to share the case study if useful.
**Variant 3 — Curiosity:**
Subject: Quick question about {{company}}'s reporting stack
Hi {{first_name}}, curious — still using spreadsheets for regulatory
reporting? I have a benchmark report for FinTech your size.
LinkedIn: "Hi {{first_name}} — I work with FinTech compliance
teams on automating regulatory reporting. Would love to connect."
Error Handling
| Error | Cause | Fix |
|---|---|---|
| Smart View returns 0 leads | Criteria too narrow | Verify in Close UI; update filters |
query field empty | Internal format | Use GET /lead/?saved_search_id={id} instead |
| Generation too generic | Segment lacks specificity | Enrich with custom fields or recent activity data |
| Rate limit on generations | Concurrent calls | Queue with 500ms delay between batches |