Scenario
You’re running ABM and need personas representing the buying committee at target accounts. You pull companies from HubSpot, enrich with Mave’s research, then create role-specific personas for each account’s buying committee.Architecture
Code
import os, requests, time
HS = os.environ["HUBSPOT_ACCESS_TOKEN"]
MV = os.environ["MAVERA_API_KEY"]
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
ROLES = [
{"role": "Economic Buyer", "desc": "C-level controlling budget. Cares about ROI and strategic alignment."},
{"role": "Technical Evaluator", "desc": "Engineering/IT lead. Evaluates integration, security, scalability."},
{"role": "End User Champion", "desc": "Day-to-day user and internal advocate. Cares about UX and time savings."},
{"role": "Procurement Gatekeeper", "desc": "Legal/procurement. Reviews compliance, terms, and risk."},
]
# 1. Target companies
companies = requests.post("https://api.hubapi.com/crm/v3/objects/companies/search",
headers={"Authorization": f"Bearer {HS}"},
json={
"filterGroups": [{"filters": [{"propertyName": "numberofemployees", "operator": "GTE", "value": "100"}]}],
"properties": ["name", "industry", "numberofemployees", "annualrevenue", "domain"],
"sorts": [{"propertyName": "annualrevenue", "direction": "DESCENDING"}],
"limit": 5,
}).json().get("results", [])
all_personas = []
for co in companies:
p = co.get("properties", {})
name = p.get("name", "Unknown")
# 2. Enrich with Mave
enrichment = requests.post("https://app.mavera.io/api/v1/mave/chat", headers=MH,
json={"message": f"Research {name} ({p.get('industry','N/A')}, ~{p.get('numberofemployees','?')} employees). Strategic priorities? Key challenges? Recent news? Buying committee for B2B SaaS?"}
).json()
context = enrichment.get("content", "")[:300]
# 3. Create buying committee personas
for role in ROLES:
persona = requests.post("https://app.mavera.io/api/v1/personas", headers=MH, json={
"name": f"{name} — {role['role']}",
"description": f"{role['desc']} Context: {p.get('industry','N/A')}, ~{p.get('numberofemployees','?')} employees. {context}",
"demographic": {"industries": [p.get("industry", "Technology")]},
}).json()
all_personas.append({"company": name, "role": role["role"], "id": persona["id"]})
time.sleep(0.2)
time.sleep(0.5)
print(f"Created {len(all_personas)} ABM personas for {len(companies)} companies")
for p in all_personas:
print(f" {p['company']} | {p['role']} | {p['id']}")
const HS = process.env.HUBSPOT_ACCESS_TOKEN;
const MV = process.env.MAVERA_API_KEY;
const MH = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
const ROLES = [
{ role: "Economic Buyer", desc: "C-level controlling budget. Cares about ROI." },
{ role: "Technical Evaluator", desc: "Engineering/IT. Evaluates security, scalability." },
{ role: "End User Champion", desc: "Day-to-day user. Cares about UX, time savings." },
{ role: "Procurement Gatekeeper", desc: "Legal/procurement. Reviews compliance, risk." },
];
const companies = await fetch("https://api.hubapi.com/crm/v3/objects/companies/search", {
method: "POST",
headers: { Authorization: `Bearer ${HS}`, "Content-Type": "application/json" },
body: JSON.stringify({
filterGroups: [{ filters: [{ propertyName: "numberofemployees", operator: "GTE", value: "100" }] }],
properties: ["name", "industry", "numberofemployees", "annualrevenue", "domain"],
sorts: [{ propertyName: "annualrevenue", direction: "DESCENDING" }], limit: 5,
}),
}).then(r => r.json()).then(d => d.results || []);
const allPersonas = [];
for (const co of companies) {
const p = co.properties || {};
const enrichment = await fetch("https://app.mavera.io/api/v1/mave/chat", {
method: "POST", headers: MH,
body: JSON.stringify({ message: `Research ${p.name}. Priorities? Challenges? Buying committee for B2B SaaS?` }),
}).then(r => r.json());
const context = (enrichment.content || "").slice(0, 300);
for (const role of ROLES) {
const persona = await fetch("https://app.mavera.io/api/v1/personas", {
method: "POST", headers: MH,
body: JSON.stringify({
name: `${p.name} — ${role.role}`,
description: `${role.desc} Context: ${p.industry}, ~${p.numberofemployees} emp. ${context}`,
demographic: { industries: [p.industry || "Technology"] },
}),
}).then(r => r.json());
allPersonas.push({ company: p.name, role: role.role, id: persona.id });
await new Promise(r => setTimeout(r, 200));
}
await new Promise(r => setTimeout(r, 500));
}
console.log(`Created ${allPersonas.length} ABM personas`);
allPersonas.forEach(p => console.log(` ${p.company} | ${p.role} | ${p.id}`));
Example Output
{ "companies": 5, "personas": 20,
"sample": { "company": "Acme Corp", "committee": [
{ "role": "Economic Buyer", "id": "per_acme_eb_1" },
{ "role": "Technical Evaluator", "id": "per_acme_te_2" },
{ "role": "End User Champion", "id": "per_acme_eu_3" },
{ "role": "Procurement Gatekeeper", "id": "per_acme_pg_4" }
], "enrichment": "Digital transformation. $50M Series C. Supply chain automation." }}
Error Handling
Mave rate limits
Mave rate limits
Mave has separate credits/limits. Code includes 500ms between companies. For 50+, add exponential backoff.
Persona name uniqueness
Persona name uniqueness
Re-running creates duplicates. Check with
GET /api/v1/personas?search={name} before creating.