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:
| Subject | Required fields | Boundary |
|---|---|---|
| Prospect | prospecting_job_id and prospect_id together | The Job must be a succeeded, non-synthetic Prospecting run and the prospect a real row in its result. |
| Account | account_domain | A valid bare domain, normalized to lowercase. |
| Campaign | campaign_id | A 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.