# Audiences

> Run evidence-backed audience discovery, then materialize immutable review snapshots from real prospects.

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

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

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

Audiences has two complementary workflows. The RTSA workflow runs asynchronous discovery and returns scored candidates. The snapshot workflow freezes selected prospects from a successful Prospecting job so people can review and export a stable list. Neither workflow authorizes or sends outreach.

## Run one audience discovery

Operation `create_audience_v1_audiences_post` accepts an `AudienceInput` at `POST /v1/audiences`. The required `objective` describes the companies and buyers to find. `target_size` is 1 through 2,000, `max_contacts_per_company` is 1 through 10, and optional seller, product, ICP, exclusion, and intent context refines the run.

```bash
JOB=$(curl --fail-with-body --silent --show-error \
  --request POST "$BLACKPEARL_API_BASE_URL/v1/audiences" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" \
  --header "Idempotency-Key: audience-run-20260717-anz-revops" \
  --header "Content-Type: application/json" \
  --data '{
    "objective": "Find revenue operations leaders at B2B SaaS companies in Australia and New Zealand.",
    "target_size": 100,
    "max_contacts_per_company": 3,
    "model": "default"
  }')

JOB_ID=$(printf '%s' "$JOB" | jq -er '.id')
```

The response is an asynchronous Audience job. Poll it using [Jobs and resumable polling](https://api.blackpearl.com/docs/jobs). Each pipeline stage is `pending`, `running`, `completed`, `skipped`, or `failed`. After the Job succeeds, operation `list_audience_candidates_v1_audiences__job_id__candidates_get` pages `GET /v1/audiences/{job_id}/candidates`. Pass each opaque `next_cursor` back unchanged and stop when it is null. Optional `q` filtering is applied before pagination.

```bash
curl --fail-with-body --silent --show-error \
  "$BLACKPEARL_API_BASE_URL/v1/audiences/$JOB_ID/candidates?limit=50" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" | jq .
```

Candidate rows are discriminated by `result_shape`: a `company` row has company scoring plus contacts, while a `contact` row is one scored contact with company context. Results remain available until the job's `expires_at`; save anything needed beyond the 30-day retention window.

## Materialize an immutable snapshot

Use a snapshot when a successful, non-synthetic Prospecting result should become a durable review set. Operation `create_audience_v1_audience_snapshots_post` accepts a caller-owned `key`, a display `name`, the source `prospecting_job_id`, and an optional subset of `prospect_ids`.

```bash
SNAPSHOT=$(curl --fail-with-body --silent --show-error \
  --request POST "$BLACKPEARL_API_BASE_URL/v1/audience-snapshots" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{
    \"key\": \"anz-revops-2026q3\",
    \"name\": \"ANZ RevOps leaders\",
    \"prospecting_job_id\": \"$PROSPECTING_JOB_ID\"
  }")

AUDIENCE_ID=$(printf '%s' "$SNAPSHOT" | jq -er '.id')
```

The create namespace is project, API-key environment, and `key`. An exact replay returns the original resource with HTTP 200; different normalized input under the same key returns `audience_idempotency_conflict`. The server stores a hash of the normalized source result and copies only validated prospect fields. A later provider or Job change cannot rewrite the snapshot.

Operation `list_audiences_v1_audience_snapshots_get` lists snapshots newest first with cursor pagination. Operation `get_audience_v1_audience_snapshots__audience_id__get` reads one snapshot. Resources in another project or `live`/`test` environment resolve as not found.

## Review members

Operation `list_audience_members_v1_audience_snapshots__audience_id__members_get` pages the frozen members. Filters include text query, review, qualification, enrichment and outreach states, minimum score, evidence or work-email presence, and exact prospect ID. Cursors are bound to the filter set; restart pagination when a filter changes.

Operation `review_audience_members_v1_audience_snapshots__audience_id__reviews_post` records an append-only `included` or `excluded` decision for 1 through 100 member IDs. Generate one `review_key` per logical decision and retain it for retries.

```bash
curl --fail-with-body --silent --show-error \
  --request POST "$BLACKPEARL_API_BASE_URL/v1/audience-snapshots/$AUDIENCE_ID/reviews" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{
    \"review_key\": \"review-20260717-batch-1\",
    \"member_ids\": [\"$AUDIENCE_MEMBER_ID\"],
    \"decision\": \"included\",
    \"reason_code\": \"verified-fit\"
  }"
```

Review means curation, not consent or delivery permission. Every snapshot and member returns `outbound_authorized: false`, including included members.

## Export and safety

Operation `export_audience_csv_v1_audience_snapshots__audience_id__export_csv_get` exports the current filtered snapshot as CSV. Treat names, emails, profile details, generated drafts, and evidence as personal or untrusted application data. Apply your own lawful-basis, suppression, consent, access-control, retention, and dispatch-time checks outside Blackpearl.

Common failures are `not_ready`, `job_expired`, `audiences_result_unavailable`, `prospecting_job_not_found`, `synthetic_prospecting_result`, `audience_idempotency_conflict`, `invalid_cursor`, entitlement, quota, and budget errors. Follow [Errors and safe retries](https://api.blackpearl.com/docs/errors).
