> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deal-Closed Content Replay

> Extract winning email copy from HubSpot Closed Won deals, distill a Brand Voice, and generate new variations

## Scenario

Your winning email copy is locked inside HubSpot engagement records. You extract emails from Closed Won deals, distill a Brand Voice from the highest-converting messaging, then generate new variations that carry the same tone and persuasion.

## Architecture

```mermaid theme={"dark"}
flowchart LR
    A["HubSpot Deals (Closed Won)"] --> B[Associated emails] --> C[Filter outbound] --> D["POST /brand-voices"] --> E["POST /generations"] --> F[New variations]
```

## Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests
  from openai import OpenAI

  HS = os.environ["HUBSPOT_ACCESS_TOKEN"]
  MV = os.environ["MAVERA_API_KEY"]
  HB = "https://api.hubapi.com/crm/v3"
  MB = "https://app.mavera.io/api/v1"

  # 1. Closed Won deals
  deals = requests.post(f"{HB}/objects/deals/search",
      headers={"Authorization": f"Bearer {HS}"},
      json={
          "filterGroups": [{"filters": [{"propertyName": "dealstage", "operator": "EQ", "value": "closedwon"}]}],
          "properties": ["dealname", "amount", "closedate"],
          "sorts": [{"propertyName": "closedate", "direction": "DESCENDING"}],
          "limit": 15,
      },
  ).json().get("results", [])

  # 2. Collect winning email copy
  winning_emails = []
  for deal in deals:
      assocs = requests.get(f"{HB}/objects/deals/{deal['id']}/associations/emails",
          headers={"Authorization": f"Bearer {HS}"}).json().get("results", [])
      for a in assocs[:5]:
          email = requests.get(f"{HB}/objects/emails/{a['id']}",
              headers={"Authorization": f"Bearer {HS}"},
              params={"properties": "hs_email_subject,hs_email_text,hs_email_direction"},
          ).json().get("properties", {})
          if email.get("hs_email_subject") and email.get("hs_email_direction") == "EMAIL":
              winning_emails.append(f"Subject: {email['hs_email_subject']}\n{email.get('hs_email_text','')[:800]}")

  # 3. Create Brand Voice
  samples = "\n\n---\n\n".join(winning_emails[:10])
  bv = requests.post(f"{MB}/brand-voices",
      headers={"Authorization": f"Bearer {MV}", "Content-Type": "application/json"},
      json={"name": "HubSpot Won Email Voice", "samples": [samples]},
  ).json()
  print(f"Brand Voice: {bv['id']}")

  # 4. Generate variations
  gen = requests.post(f"{MB}/generations",
      headers={"Authorization": f"Bearer {MV}", "Content-Type": "application/json"},
      json={
          "brand_voice_id": bv["id"],
          "prompt": "Write 3 sales email variants for a mid-market SaaS prospect. Subject line + 150-word body each. Match the winning tone.",
          "count": 3,
      },
  ).json()
  for i, g in enumerate(gen.get("results", [gen]), 1):
      print(f"\nVariant {i}:\n{g.get('content', g.get('text',''))[:300]}")
  ```

  ```javascript JavaScript theme={"dark"}
  const HS = process.env.HUBSPOT_ACCESS_TOKEN;
  const MV = process.env.MAVERA_API_KEY;
  const HB = "https://api.hubapi.com/crm/v3";
  const MB = "https://app.mavera.io/api/v1";
  const h = (tok) => ({ Authorization: `Bearer ${tok}`, "Content-Type": "application/json" });

  // 1. Closed Won deals
  const deals = await fetch(`${HB}/objects/deals/search`, {
    method: "POST", headers: h(HS),
    body: JSON.stringify({
      filterGroups: [{ filters: [{ propertyName: "dealstage", operator: "EQ", value: "closedwon" }] }],
      properties: ["dealname", "amount", "closedate"],
      sorts: [{ propertyName: "closedate", direction: "DESCENDING" }],
      limit: 15,
    }),
  }).then(r => r.json()).then(d => d.results || []);

  // 2. Collect winning emails
  const winningEmails = [];
  for (const deal of deals) {
    const assocs = await fetch(`${HB}/objects/deals/${deal.id}/associations/emails`,
      { headers: h(HS) }).then(r => r.json()).then(d => d.results || []);
    for (const a of assocs.slice(0, 5)) {
      const email = await fetch(`${HB}/objects/emails/${a.id}?properties=hs_email_subject,hs_email_text,hs_email_direction`,
        { headers: h(HS) }).then(r => r.json()).then(d => d.properties || {});
      if (email.hs_email_subject && email.hs_email_direction === "EMAIL")
        winningEmails.push(`Subject: ${email.hs_email_subject}\n${(email.hs_email_text || "").slice(0, 800)}`);
    }
  }

  // 3. Brand Voice
  const bv = await fetch(`${MB}/brand-voices`, {
    method: "POST", headers: h(MV),
    body: JSON.stringify({ name: "HubSpot Won Email Voice", samples: [winningEmails.slice(0, 10).join("\n\n---\n\n")] }),
  }).then(r => r.json());
  console.log(`Brand Voice: ${bv.id}`);

  // 4. Generate
  const gen = await fetch(`${MB}/generations`, {
    method: "POST", headers: h(MV),
    body: JSON.stringify({
      brand_voice_id: bv.id,
      prompt: "Write 3 sales email variants for a mid-market SaaS prospect. Subject + 150-word body. Match the winning tone.",
      count: 3,
    }),
  }).then(r => r.json());
  (gen.results || [gen]).forEach((g, i) =>
    console.log(`\nVariant ${i+1}:\n${(g.content || g.text || "").slice(0, 300)}`)
  );
  ```
</CodeGroup>

## Example Output

```text theme={"dark"}
Brand Voice: bv_won_email_9f3a

Variant 1: Subject: Quick question about your Q3 pipeline
Hey [Name], I noticed [Company] is scaling — congrats. We helped [Similar Co]
cut pipeline review time by 40%. Worth a 15-min call?

Variant 2: Subject: [Company] + [Product] — a thought
Your growth caught my eye. We work with companies at your stage to solve
[specific pain]. I put together a quick brief — want it?
```

## Error Handling

<AccordionGroup>
  <Accordion title="No email associations">Not all deals have associated emails. Confirm your team logs emails to deals in HubSpot Settings.</Accordion>
  <Accordion title="Brand Voice sample size">Under \~200 words total produces a generic voice. Aim for 5–10 emails, 100+ words each.</Accordion>
</AccordionGroup>

***

<CardGroup cols={2}>
  <Card title="HubSpot Integration" icon="arrow-left" href="/integrations/hubspot" />

  <Card title="Brand Voice API" icon="microphone" href="/features/brand-voice" />
</CardGroup>
