Feedback and outcomes

Append external prospect, account, or campaign results and aggregate them across the GTM graph.

Outcomes is the append-only feedback ledger. Your delivery, CRM, or calendar tooling records what happened; Blackpearl validates its attribution and returns deterministic aggregates. Recording an Outcome does not verify the assertion, send a message, update a CRM, or train a model.

Record an outcome#

Operation create_outcome_v1_outcomes_post accepts exactly one logical event at POST /v1/outcomes.

curl --fail-with-body --silent --show-error \
  --request POST "$BLACKPEARL_API_BASE_URL/v1/outcomes" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{
    \"source\": \"manual\",
    \"external_event_id\": \"meeting-20260717-018f6f\",
    \"type\": \"meeting_booked\",
    \"occurred_at\": \"2026-07-17T02:15:00Z\",
    \"prospecting_job_id\": \"$PROSPECTING_JOB_ID\",
    \"prospect_id\": \"$PROSPECT_ID\",
    \"campaign_id\": \"$CAMPAIGN_ID\",
    \"offer_id\": \"$OFFER_ID\",
    \"channel\": \"email\"
  }"

At least one subject is required:

SubjectRequired fieldsBoundary
Prospectprospecting_job_id and prospect_id togetherThe Job must be a succeeded, non-synthetic Prospecting run and the prospect a real row in its result.
Accountaccount_domainA valid bare domain, normalized to lowercase.
Campaigncampaign_idA Campaign in the API key's project.

Optional campaign_id, offer_id, brand_profile_id, audience_id, playbook_job_id, and message_template_revision_id references are validated before insertion. A prospect subject can also carry these attribution fields.

For manual events, omit connector_id. A non-manual source requires a project Connection whose provider key matches the source. Connections are currently Preview; see Connector inventory before depending on provider ingestion.

Taxonomy and learning safety#

Preference types are qualification_approved, qualification_rejected, draft_approved, and draft_rejected. Commercial types are positive_reply, negative_reply, meeting_booked, sales_qualified, opportunity_created, closed_won, closed_lost, and ghosted. Operational types are delivered, bounced, unsubscribed, email_not_found, and provider_failed.

The server derives classification and whether the type is a possible learning_candidate. Every currently accepted row is still verification_status: unverified and eligible_for_learning: false. Operational events and ghosted are never learning candidates; provider availability and silence must not be mistaken for poor fit.

amount_usd_cents is a strict integer accepted only for closed_won. Raw webhook bodies, credentials, prompts, message content, and arbitrary metadata are rejected.

Idempotency and listing#

The idempotency namespace combines project, API-key environment, source connection or manual namespace, and external_event_id. An exact retry returns HTTP 200 with idempotent_replay: true; different normalized data under the same namespace returns outcome_idempotency_conflict.

Operation list_outcomes_v1_outcomes_get lists rows newest first. Filter by type, classification, subject kind, prospecting Job, prospect, account domain, Campaign, or Offer. Use next_cursor unchanged and restart pagination when filters change.

Aggregate insights#

Operation outcome_insights_v1_outcomes_insights_get groups the ledger by campaign, offer, brand_profile, audience, playbook_job, message_template_revision, type, channel, or account_domain. Optional since is inclusive and until is exclusive.

curl --fail-with-body --silent --show-error \
  "$BLACKPEARL_API_BASE_URL/v1/outcomes/insights?group_by=campaign&campaign_id=$CAMPAIGN_ID" \
  --header "Authorization: Bearer $BLACKPEARL_API_KEY" | jq .

Aggregates report counts, classification distribution, positive replies, meetings, wins, losses, win rate, closed-won revenue, and learning-candidate count. They summarize unverified submitted facts; they do not make them verified.