> ## 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.

# Job Distribution → Performance-Optimized Descriptions

> Post jobs to LinkedIn, track performance, and use Mavera Focus Groups + Generate to iterate job descriptions for higher apply rates

## Scenario

You distribute job postings through LinkedIn using the Simple Job Posting API. After posting, you track view and apply rates. When a posting underperforms, you run the description through a Mavera Focus Group to identify weaknesses, then use Generate to create improved versions — and repost. This creates a feedback loop: post → measure → test → iterate → repost.

**Flow:** LinkedIn `POST /rest/simpleJobPostings` → Track view/apply rates → Mavera `POST /focus-groups` (test current description) → `POST /generations` (improved version) → LinkedIn `POST /rest/simpleJobPostings` (updated)

### Architecture

```mermaid theme={"dark"}
flowchart LR
    A["LinkedIn POST /rest/simpleJobPostings"] --> B["Track views + applies"]
    B --> C["POST /api/v1/focus-groups"]
    C --> D["POST /api/v1/generations"]
    D --> E["LinkedIn POST updated version"]
    E --> F["Compare performance A vs B"]
```

## Code

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

  LI = os.environ["LINKEDIN_ACCESS_TOKEN"]
  MV = os.environ["MAVERA_API_KEY"]
  LI_BASE = "https://api.linkedin.com/rest"
  MV_BASE = "https://app.mavera.io/api/v1"
  LI_H = {
      "Authorization": f"Bearer {LI}",
      "Content-Type": "application/json",
      "LinkedIn-Version": "202401",
      "X-Restli-Protocol-Version": "2.0.0",
  }
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

  # 1. Post a job
  job_posting = {
      "integrationContext": "urn:li:organization:12345",
      "jobPostingOperationType": "CREATE",
      "title": "Senior Backend Engineer",
      "description": {
          "text": (
              "We're looking for a Senior Backend Engineer to join our platform team. "
              "You'll design and build APIs that serve 10M+ requests/day, mentor junior engineers, "
              "and drive architecture decisions. Stack: Python, Go, PostgreSQL, Kubernetes. "
              "5+ years experience required. Competitive salary, equity, and fully remote."
          ),
      },
      "location": "San Francisco, CA",
      "listedAt": int(time.time() * 1000),
      "jobPostingStatus": "LISTED",
  }

  post_resp = requests.post(f"{LI_BASE}/simpleJobPostings",
      headers=LI_H, json=job_posting)
  post_resp.raise_for_status()
  job_id = post_resp.headers.get("X-RestLi-Id", "unknown")
  print(f"Posted job: {job_id}")

  # 2. Wait for data to accumulate (in production, run this days later)
  time.sleep(2)

  # 3. Simulate performance metrics (replace with real analytics in production)
  metrics = {
      "views": 1240,
      "applies": 31,
      "apply_rate": 2.5,
      "benchmark_apply_rate": 5.0,
  }

  # 4. If underperforming, test with Focus Group
  if metrics["apply_rate"] < metrics["benchmark_apply_rate"]:
      print(f"Apply rate {metrics['apply_rate']}% below benchmark {metrics['benchmark_apply_rate']}%")

      candidate_personas = []
      for archetype in [
          {"name": "Passive Staff Engineer", "desc": "10+ yrs, employed at FAANG. Only moves for exceptional roles."},
          {"name": "Active Senior IC", "desc": "5-7 yrs, actively looking. Applying to 10+ roles. Values clarity."},
          {"name": "Career Transitioner", "desc": "Backend dev moving from enterprise to startup. Evaluating risk."},
      ]:
          p = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
              "name": f"LI Talent: {archetype['name']}",
              "description": archetype["desc"],
          }).json()
          candidate_personas.append(p["id"])
          time.sleep(0.2)

      fg = requests.post(f"{MV_BASE}/focus-groups", headers=MV_H, json={
          "name": f"Job Posting Review: {job_posting['title']}",
          "persona_ids": candidate_personas,
          "questions": [
              {"type": "likert", "text": "Rate appeal of this posting (1=skip, 5=apply now)", "scale": 5},
              "What about this posting makes you hesitant to apply?",
              "What information is missing that you'd need before applying?",
              "How does this compare to other Senior Backend Engineer postings you've seen?",
              "Rewrite the first two sentences to make them more compelling for YOU.",
          ],
          "context": job_posting["description"]["text"],
          "responses_per_persona": 3,
      }).json()

      for _ in range(20):
          time.sleep(5)
          fg_data = requests.get(f"{MV_BASE}/focus-groups/{fg['id']}", headers=MV_H).json()
          if fg_data.get("status") == "completed":
              break

      feedback_summary = "\n".join(
          f"- [{r.get('persona_id','?')[:8]}] {r.get('question','')[:40]}: {r.get('answer','')[:200]}"
          for r in fg_data.get("responses", [])
      )

      # 5. Generate improved description
      gen = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
          "prompt": (
              f"Rewrite this job posting based on candidate feedback.\n\n"
              f"ORIGINAL:\n{job_posting['description']['text']}\n\n"
              f"FEEDBACK:\n{feedback_summary}\n\n"
              f"REQUIREMENTS:\n"
              f"- Address every concern raised\n"
              f"- Keep under 300 words\n"
              f"- Lead with impact, not requirements\n"
              f"- Include salary range and specific benefits\n"
              f"- Make the first sentence irresistible"
          ),
      }).json()

      improved = gen.get("output", gen.get("content", gen.get("text", "")))
      print(f"\n=== Improved Description ===\n{improved[:800]}")

      # 6. Update the posting (in production)
      # job_posting["description"]["text"] = improved
      # job_posting["jobPostingOperationType"] = "UPDATE"
      # requests.post(f"{LI_BASE}/simpleJobPostings", headers=LI_H, json=job_posting)
  ```

  ```javascript JavaScript theme={"dark"}
  const LI = process.env.LINKEDIN_ACCESS_TOKEN;
  const MV = process.env.MAVERA_API_KEY;
  const LI_BASE = "https://api.linkedin.com/rest";
  const MV_BASE = "https://app.mavera.io/api/v1";
  const LI_H = {
    Authorization: `Bearer ${LI}`, "Content-Type": "application/json",
    "LinkedIn-Version": "202401", "X-Restli-Protocol-Version": "2.0.0",
  };
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };

  // 1. Post job
  const jobPosting = {
    integrationContext: "urn:li:organization:12345",
    jobPostingOperationType: "CREATE",
    title: "Senior Backend Engineer",
    description: {
      text: "We're looking for a Senior Backend Engineer to join our platform team. " +
        "You'll design and build APIs serving 10M+ req/day, mentor juniors, drive architecture. " +
        "Stack: Python, Go, PostgreSQL, Kubernetes. 5+ years. Competitive salary, equity, fully remote.",
    },
    location: "San Francisco, CA",
    listedAt: Date.now(),
    jobPostingStatus: "LISTED",
  };

  const postResp = await fetch(`${LI_BASE}/simpleJobPostings`, {
    method: "POST", headers: LI_H, body: JSON.stringify(jobPosting),
  });
  if (!postResp.ok) throw new Error(`LinkedIn ${postResp.status}`);
  const jobId = postResp.headers.get("X-RestLi-Id") || "unknown";
  console.log(`Posted: ${jobId}`);

  // 2. Simulated metrics (replace with real analytics)
  const metrics = { views: 1240, applies: 31, applyRate: 2.5, benchmark: 5.0 };

  // 3. Focus Group if underperforming
  if (metrics.applyRate < metrics.benchmark) {
    console.log(`Apply rate ${metrics.applyRate}% below ${metrics.benchmark}% benchmark`);

    const archetypes = [
      { name: "Passive Staff Engineer", desc: "10+ yrs, FAANG. Only moves for exceptional roles." },
      { name: "Active Senior IC", desc: "5-7 yrs, actively looking. Compares 10+ roles." },
      { name: "Career Transitioner", desc: "Enterprise to startup. Evaluating risk." },
    ];

    const personaIds = [];
    for (const arch of archetypes) {
      const p = await fetch(`${MV_BASE}/personas`, {
        method: "POST", headers: MV_H,
        body: JSON.stringify({ name: `LI: ${arch.name}`, description: arch.desc }),
      }).then((r) => r.json());
      personaIds.push(p.id);
      await new Promise((r) => setTimeout(r, 200));
    }

    const fg = await fetch(`${MV_BASE}/focus-groups`, {
      method: "POST", headers: MV_H,
      body: JSON.stringify({
        name: `Posting Review: ${jobPosting.title}`,
        persona_ids: personaIds,
        questions: [
          { type: "likert", text: "Rate appeal (1=skip, 5=apply now)", scale: 5 },
          "What makes you hesitant to apply?",
          "What information is missing?",
          "How does this compare to similar postings?",
          "Rewrite the first two sentences for YOU.",
        ],
        context: jobPosting.description.text,
        responses_per_persona: 3,
      }),
    }).then((r) => r.json());

    let fgData;
    for (let i = 0; i < 20; i++) {
      await new Promise((r) => setTimeout(r, 5000));
      fgData = await fetch(`${MV_BASE}/focus-groups/${fg.id}`, { headers: MV_H }).then((r) => r.json());
      if (fgData.status === "completed") break;
    }

    const feedbackSummary = (fgData.responses || [])
      .map((r) => `- ${(r.question || "").slice(0, 40)}: ${(r.answer || "").slice(0, 200)}`)
      .join("\n");

    // 4. Generate improved version
    const gen = await fetch(`${MV_BASE}/generations`, {
      method: "POST", headers: MV_H,
      body: JSON.stringify({
        prompt: `Rewrite this job posting based on feedback.\n\nORIGINAL:\n${jobPosting.description.text}\n\nFEEDBACK:\n${feedbackSummary}\n\nAddress every concern. Under 300 words. Lead with impact. Include salary range.`,
      }),
    }).then((r) => r.json());

    console.log("\n=== Improved ===");
    console.log((gen.output || gen.content || gen.text || "").slice(0, 800));
  }
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Apply rate 2.5% below benchmark 5.0%

Focus Group feedback:
- [Passive Staff] Appeal: 2/5. "Generic. Every company says 'APIs at scale.' What makes YOUR APIs interesting?"
- [Active Senior] Missing info: "No salary range. I won't apply without knowing comp."
- [Transitioner] Hesitant: "'5+ years required' — I have 4 years backend + 3 years adjacent. Am I welcome?"

=== Improved Description ===
Our platform processes 10M+ API requests per day — and we need your help
making that feel like 10. As a Senior Backend Engineer, you'll own the
request lifecycle from edge to database, eliminate bottlenecks that wake
people up at 3am, and mentor a team of 4 engineers who ship weekly.

What you'll actually do:
- Redesign our payment processing pipeline (currently 800ms → target 200ms)
- Build the multi-region architecture for our APAC launch
- Lead our Python → Go migration for latency-critical services

Compensation: $185-225K base + 0.1-0.2% equity + full remote (async-first)

We're looking for someone with 4+ years of backend experience who has
opinions about database design and isn't afraid of a Kubernetes manifest.
Career changers with relevant experience welcome — we care about what you
can build, not where you built it.
```

### Error Handling

<AccordionGroup>
  <Accordion title="Partner access required">The Simple Job Postings API returns `403` without partner approval. Apply at LinkedIn Developer Portal. For testing, mock the LinkedIn calls and focus on the Mavera feedback loop.</Accordion>
  <Accordion title="LinkedIn-Version header">All REST API calls require the `LinkedIn-Version` header (format: `YYYYMM`). Using an outdated version returns `400`. Update quarterly.</Accordion>
  <Accordion title="Analytics delay">LinkedIn job analytics aren't real-time. Allow 24-48 hours after posting before checking performance. The code simulates metrics — replace with real analytics calls in production.</Accordion>
</AccordionGroup>
