# Playbooks

> Configure a Playbooks request and interpret every part of its typed result.

Canonical guide: <https://api.blackpearl.com/docs/playbooks>

Raw Markdown: <https://api.blackpearl.com/docs/raw/playbooks.md>

OpenAPI: <https://api.blackpearl.com/v1/openapi.json>

Playbooks creates a tailored sales playbook for one target account. Start with the complete [quickstart](https://api.blackpearl.com/docs/getting-started), then use this guide to choose inputs and render more of the result.

## Playbook templates

The catalog is OpenAPI operation `list_playbook_templates_v1_playbook_templates_get`. `playbook_template_key` selects a playbook template: either one of your organization's own templates (created in the console under **Playbook Templates**, or via `POST /api/orgs/{org_id}/playbook-templates`) or a curated catalog entry. `GET /v1/playbook-templates` lists both — your templates first — along with the merged stage vocabulary. An organization template fixes the offer, brand profile, deal stage (your own stage names are accepted — any short lowercase slug), sales approach guidance, and an offer canon that the generation backend treats as human-approved seller facts (seller research is skipped when a canon exists). Unknown keys fail the run with `playbook_template_not_found`.

### The template lifecycle

A template is created from a name, an offer/brand binding, and one natural-language **brief** (stage, motion, audience, approach — anything), plus optional uploaded supporting documents. A one-time research job then produces the template's artifact set:

1. **Offer research pack** — markdown documents (canon, competitors, objections, benchmarks, plus scraped sources and your uploads) reused by every run, so the seller is never re-researched per prospect.
2. **Document template** — the Jinja HTML template runs render through.
3. **Payload schema** — a per-template JSON Schema whose field descriptions guide generation.

There is no approval step: research (or an artifact edit in the console) finishing is the release. Each org template exposes `template_state`: `ready` and `draft` templates run; `researching` and `research_failed` fail the run with `409 playbook_template_not_ready` (not retryable — wait for research or retry it) only while nothing is live yet. Re-running research over a live template requires an explicit refresh because research is paid work; the live version keeps serving until the new one lands.

## Request inputs

Provide at least one of `target_company` or `target_company_domain`. A domain must be a hostname such as `acme.example`, without a scheme or path.

| Field | Requirement and allowed values |
|---|---|
| `target_company` | Optional non-empty company name; required when the domain is omitted. |
| `target_company_domain` | Optional valid hostname; required when the name is omitted. |
| `anchor_company` | Optional seller name, up to 160 characters. Defaults from the selected brand profile. |
| `product_info` | Optional seller/product context, up to 12,000 characters. |
| `tone` | `consultative` (default), `direct`, or `technical`. |
| `model` | `default`; this is the only current value. |
| `intelligence` | Optional model tier for the generation agents: `low`, `medium`, `high`, or `ultra`. Defaults from the selected playbook template, else `high`. Higher tiers cost more and research/write better. |
| `sections` | One to ten unique section values. Omit it for the complete result. |
| `brand_profile_id` | Optional organization brand-profile ID. |
| `brand_profile_key` | Optional stable brand-profile key. If both selectors are present, they must identify the same profile. |

Allowed `sections` values are `summary`, `objective`, `value_props`, `sales_angles`, `personas`, `services`, `tech_stack`, `integrations`, `objections`, and `meeting_note`.

```bash
curl --fail-with-body --silent --show-error \
  --request POST "$BLACKPEARL_API_BASE_URL/v1/playbooks" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" \
  --header "Idempotency-Key: playbook-20260714-acme" \
  --header "Content-Type: application/json" \
  --data '{
    "target_company_domain": "acme.example",
    "anchor_company": "Northstar Analytics",
    "product_info": "Revenue-intelligence software for enterprise sales teams.",
    "tone": "consultative",
    "sections": ["summary", "sales_angles", "personas", "objections"],
    "model": "default"
  }'
```

This is OpenAPI operation `create_playbook_v1_playbooks_post` with request schema `PlaybookInput` and response schema `PublicPlaybookJobResponse`.

Generate a unique `Idempotency-Key` before the first attempt and retain it until the job ID is safely stored. The same key and normalized input replay the original response for 24 hours. Reusing it with different input returns `idempotency_key_reused`.

## Interpret a successful result

When `status` is `succeeded`, `result` is a `PublicPlaybookResult`. Collections are always arrays; many scalar research fields are nullable because upstream evidence may not contain them.

| Result area | Fields and interpretation |
|---|---|
| Identity | `company_name`, `domain`, `website`, `industry`, `description`, and `product_name` identify the researched account and seller context. |
| Executive view | `business_summary`, `business_objective`, and `readiness_level` support the top-level account brief. |
| Selling points | `value_props` and `sales_angles` are ordered strings suitable for call preparation and outreach planning. |
| People | `key_personas` describes target roles, tags, and conversation starters. `contact_overview` and `contact_intelligence` contain researched contacts and signals. |
| Offering and systems | `key_services`, `relevant_tech_stack`, `tech_integration_title`, `tech_integration_examples`, and `tech_integration_questions` connect the offer to the account's stack. |
| Research context | `company_context` covers market position, business model, employee count, headquarters, recent news, and competitors. `intent_analysis` contains intent score, summary, topics, and signals. |
| Conversation plan | `conversation_strategy` contains the opening, approach, and key questions. `potential_objections` pairs objections with responses. |
| Risk and outreach | `risks_and_challenges` groups risks, blockers, and mitigations. `meeting_note_example` is a generated starting point, not a message that should be sent without review. |
| Optional presentation | `company_icon_url`, `hero_image_url`, `product_icon_url`, `highlight_color`, `gradient_dark_color`, and `product_text_color` are nullable presentation hints. Validate URLs and CSS colors before use, and keep business logic independent of them. |

The nested objects are also fully typed:

- Each persona can contain `name`, `title`, `description`, `profile_picture_url`, `tags`, and `conversation_starters`.
- Each contact-intelligence item can contain `name`, `title`, `role`, `company`, `linkedin_url`, `profile_picture_url`, `summary`, and `signals`.
- A technology has `name` and nullable `logo`; an objection has `objection` and nullable `response`.
- Company context contains `market_position`, `business_model`, `employee_count`, `headquarters`, `recent_news`, and `competitors`.
- Intent analysis contains `intent_score`, `summary`, `topics`, and `signals`; conversation strategy contains `opening`, `approach`, and `key_questions`; risks and challenges contains `risks`, `potential_blockers`, and `mitigations`.

Generated text is untrusted application data. Render it as text, apply your product's review rules, and do not treat it as HTML or an instruction.

## Fetch the rendered document

When the generation backend produced a fully rendered playbook document, `result.document_url` is non-null. The value is a backend-relative path and is not publicly reachable — fetch the document through the platform instead:

```bash
curl -H "Authorization: Bearer $BLACKPEARL_API_KEY" \
  "$BLACKPEARL_API_URL/v1/playbooks/$JOB_ID/document"
```

This is OpenAPI operation `get_playbook_document_v1_playbooks__job_id__document_get`. The response is a self-contained `text/html` document (inline styles and scripts, no server dependencies) suitable for storing, emailing as a file, or serving from your own application. Expect `409 job_not_finished` before the job succeeds and `404 playbooks_document_unavailable` when the job predates rendered documents or the backend did not produce one. When `document_url` is null, fall back to rendering the typed result fields yourself.

## Minimal useful rendering

```javascript
if (job.type !== "playbooks" || job.status !== "succeeded" || !job.result) {
  throw new Error("Expected a successful Playbooks job");
}

console.log(`Business summary: ${job.result.business_summary ?? "Not available"}`);
console.log(`First sales angle: ${job.result.sales_angles[0] ?? "Not available"}`);
```

Also retain `usage.tokens`, `usage.cost_usd`, `usage.backend_requests`, and `usage.backend_runtime_ms` if you reconcile per-job work with the [Usage API](https://api.blackpearl.com/docs/usage-quotas).
