Atribu
API Reference

Campaigns

Campaign performance, ROAS, ad-level breakdowns, and daily spend trends.

Campaigns

Top Campaigns

Endpoint
GET /api/v1/campaigns

Returns top-performing campaigns ranked by attributed outcome value, with ROAS and spend data. Pass level to drill down to ad sets or individual ads.

Scope: campaigns:read

Parameters

ParameterTypeRequiredDescription
date_fromstringYesStart date in YYYY-MM-DD format.
date_tostringYesEnd date in YYYY-MM-DD format.
modelstringNoAttribution model. Default last_touch. Options: first_touch, linear, position_based, time_decay, last_non_direct.
limitnumberNoMaximum results. Default 10, max 100.
levelstringNoHierarchy level: campaign, ad_set, or ad. When set, returns detailed performance fields.

Request

cURL
curl -H "Authorization: Bearer atb_live_YOUR_KEY" \
  "https://www.atribu.app/api/v1/campaigns?date_from=2026-03-01&date_to=2026-03-25&model=last_touch&limit=5"
JavaScript
const res = await fetch(
  "https://www.atribu.app/api/v1/campaigns?date_from=2026-03-01&date_to=2026-03-25&model=last_touch&limit=5",
  { headers: { Authorization: "Bearer atb_live_YOUR_KEY" } }
);
const { data, meta } = await res.json();
Python
import requests

res = requests.get(
    "https://www.atribu.app/api/v1/campaigns",
    headers={"Authorization": "Bearer atb_live_YOUR_KEY"},
    params={
        "date_from": "2026-03-01",
        "date_to": "2026-03-25",
        "model": "last_touch",
        "limit": 5,
    },
)
data = res.json()["data"]

Response

Success response (200 OK)
{
  "data": [
    {
      "campaign_id": "uuid",
      "campaign_name": "Spring Sale - Conversions",
      "spend": 1800.00,
      "outcome_count": 45,
      "outcome_value": 6200.00,
      "roas": 3.44
    }
  ],
  "meta": {
    "date_from": "2026-03-01",
    "date_to": "2026-03-25",
    "profile_id": "uuid"
  }
}

Response fields

FieldTypeDescription
campaign_idstringInternal campaign UUID.
campaign_namestringHuman-readable campaign name from the ad platform.
spendnumberTotal ad spend in your reporting currency.
outcome_countnumberNumber of attributed conversions.
outcome_valuenumberTotal attributed cash revenue.
roasnumberReturn on ad spend (outcome_value / spend).

Ad-level detail

Pass level=ad to get granular performance per ad creative. This adds additional fields to each row.

cURL — ad-level breakdown
curl -H "Authorization: Bearer atb_live_YOUR_KEY" \
  "https://www.atribu.app/api/v1/campaigns?date_from=2026-03-01&date_to=2026-03-25&level=ad"
JavaScript — ad-level breakdown
const res = await fetch(
  "https://www.atribu.app/api/v1/campaigns?date_from=2026-03-01&date_to=2026-03-25&level=ad",
  { headers: { Authorization: "Bearer atb_live_YOUR_KEY" } }
);
const { data } = await res.json();
Python — ad-level breakdown
res = requests.get(
    "https://www.atribu.app/api/v1/campaigns",
    headers={"Authorization": "Bearer atb_live_YOUR_KEY"},
    params={"date_from": "2026-03-01", "date_to": "2026-03-25", "level": "ad"},
)
data = res.json()["data"]

Additional fields when level is set

FieldTypeDescription
entity_levelstringThe level of this row (campaign, ad_set, ad).
parent_namestringName of the parent entity (campaign or ad set).
impressionsnumberTotal impressions served.
clicksnumberTotal clicks.
reachnumberUnique accounts reached.
ctrnumberClick-through rate (%).
avg_cpmnumberAverage cost per 1,000 impressions.
avg_cpcnumberAverage cost per click.
cacnumberCustomer acquisition cost (spend / outcome_count).
statusstringEntity status (ACTIVE, PAUSED, etc.).
objectivestringCampaign objective.
daily_budgetnumberDaily budget if set on the platform.

Campaign Trend

Endpoint
GET /api/v1/campaigns/trend

Returns daily spend, impressions, and clicks for up to 10 specific campaigns, ad sets, or ads. Use this to render sparklines or compare entity performance over time.

Scope: campaigns:read

Parameters

ParameterTypeRequiredDescription
date_fromstringYesStart date in YYYY-MM-DD format.
date_tostringYesEnd date in YYYY-MM-DD format.
entity_idsstringYesComma-separated list of entity UUIDs (max 10).
levelstringNocampaign, ad_set, or ad. Default campaign.

Request

cURL
curl -H "Authorization: Bearer atb_live_YOUR_KEY" \
  "https://www.atribu.app/api/v1/campaigns/trend?date_from=2026-03-20&date_to=2026-03-25&entity_ids=uuid1,uuid2&level=campaign"
JavaScript
const ids = ["uuid1", "uuid2"].join(",");
const res = await fetch(
  `https://www.atribu.app/api/v1/campaigns/trend?date_from=2026-03-20&date_to=2026-03-25&entity_ids=${ids}&level=campaign`,
  { headers: { Authorization: "Bearer atb_live_YOUR_KEY" } }
);
const { data } = await res.json();
Python
import requests

res = requests.get(
    "https://www.atribu.app/api/v1/campaigns/trend",
    headers={"Authorization": "Bearer atb_live_YOUR_KEY"},
    params={
        "date_from": "2026-03-20",
        "date_to": "2026-03-25",
        "entity_ids": "uuid1,uuid2",
        "level": "campaign",
    },
)
data = res.json()["data"]

Response

Success response (200 OK)
{
  "data": [
    { "entity_id": "uuid1", "date": "2026-03-20", "spend": 120.00, "impressions": 15000, "clicks": 340 },
    { "entity_id": "uuid1", "date": "2026-03-21", "spend": 135.00, "impressions": 16200, "clicks": 380 },
    { "entity_id": "uuid2", "date": "2026-03-20", "spend": 95.00, "impressions": 11800, "clicks": 275 }
  ],
  "meta": {
    "date_from": "2026-03-20",
    "date_to": "2026-03-25",
    "profile_id": "uuid"
  }
}

Response fields

FieldTypeDescription
entity_idstringThe campaign, ad set, or ad UUID.
datestringCalendar date (YYYY-MM-DD).
spendnumberAd spend for that entity on that day.
impressionsnumberImpressions served.
clicksnumberClicks recorded.

Entity ID format

entity_ids expects Atribu internal UUIDs (from the campaign_id field in the Top Campaigns response), not platform-specific IDs. You can pass up to 10 IDs in a single request.


Top Performers

Endpoint
GET /api/v1/top-performers

The profile's best-performing ads, scored against comparable creative — a cohort = channel × format × objective × audience warmth × geo × placement. The score is cohort-normalized, empirical-Bayes-smoothed (a small-sample ad shrinks toward the cohort mean — it lands mid-pack, the honest "we don't know yet"), and maturity-staged. So a $500/mo clinic and a $30k/mo clinic are ranked apples-to-apples.

Each ad carries three distinct measures — never merge them:

  • composite_score (0–100) — a transparent rule-based blend of the ad's within-cohort percentiles across funnel layers. The headline rank.
  • top_performer_likelihood (0–1) — a probability: a likelihood, not a guarantee. When score_source is model it's the calibrated output of a LambdaMART creative ranker (model_version tells you which model); otherwise (score_source is rules) it's a monotone function of composite_score. It is not ROAS and not lift.
  • attributed_revenue / roas (and attributed_outcomes_total / attributed_pipeline_outcomes / attributed_pipeline_value) — real Atribu-attributed outcomes. truth_grade='attributed' means Atribu deterministically attributed ≥1 outcome of any kind to this ad (cash payments or pipeline conversions — leads, appointments, closed-won). meta_reported_conversions / meta_reported_conversion_value are a separate, lower-confidence signal — Meta's own last-click count for the ad, not Atribu's chain; they never set truth_grade.

primary_outcome_kindcash · pipeline · messaging · meta · none tells you which of the above to headline for a given ad (a lead-gen ad shows pipeline outcomes, a Messages ad shows conversations started, an ad with only Meta-reported conversions shows meta_reported_conversions labeled as Meta's attribution, none = no attributed outcome yet → use composite_score).

maturity_stage (coldearlymaturecalibrated) says how settled the score is — act on mature/calibrated, treat cold as provisional. reason_codes explain why an ad ranks (which funnel layer is strong or weak, each with a sample_confidence band). Scores refresh on a daily cadence.

Scope: campaigns:read

Parameters

ParameterTypeRequiredDescription
windowstringNoRolling lookback: 7d, 14d, 28d (default), or lifetime. Not a custom date range.
limitnumberNoMaximum ads. Default 10, max 50.
min_spendnumberNoOnly ads with at least this much spend in the window.
objectivesstringNoComma-separated cohort objectives to keep (messaging, sales, leads, traffic, awareness).
truth_gradesstringNoComma-separated: predicted, attributed, lift.
outcome_kindsstringNoComma-separated headline-outcome kinds to keep: cash, pipeline, messaging, meta, none.
formatsstringNoComma-separated creative formats (ugc_video, talking_head, static, carousel, …).
has_videobooleanNotrue to keep only ads with a video creative; false for only static.

Request

cURL
curl -H "Authorization: Bearer atb_live_YOUR_KEY" \
  "https://www.atribu.app/api/v1/top-performers?window=28d&limit=5&truth_grades=attributed"

Response

Success response (200 OK)
{
  "data": [
    {
      "ad_external_id": "120210000000000123",
      "ad_name": "UGC — before/after — DM offer",
      "campaign_name": "Always-on — Messaging",
      "ad_set_name": "Prospecting — broad",
      "creative_thumbnail_url": "https://…",
      "video_id": "987654321",
      "score_window": "28d",
      "composite_score": 78,
      "top_performer_likelihood": 0.81,
      "model_version": 3,
      "score_source": "model",
      "maturity_stage": "mature",
      "truth_grade": "attributed",
      "primary_outcome_kind": "messaging",
      "cohort_key": "meta|ugc_video|messaging|prospecting|geo_any|advantage",
      "cohort_objective": "messaging",
      "cohort_format": "ugc_video",
      "cohort_audience_warmth": "prospecting",
      "cohort_n_ads": 17,
      "hook_type": "before_after",
      "creative_format": "ugc_video",
      "cta_type": "send_dm",
      "primary_angle": "fast visible results",
      "offers": ["free consultation"],
      "spend": 4120.0,
      "impressions": 512000,
      "ctr": 1.42,
      "cpc": 0.57,
      "attributed_cash_outcomes": 6,
      "attributed_revenue": 9200.0,
      "roas": 2.23,
      "cac": 686.67,
      "attributed_outcomes_total": 18,
      "attributed_pipeline_outcomes": 12,
      "attributed_pipeline_value": 6400.0,
      "meta_reported_conversions": 0,
      "meta_reported_conversion_value": 0.0,
      "cost_per_conversation": 0.33,
      "messaging_conversations_started": 412,
      "first_reply_rate": 41.2,
      "avg_engagement_score": null,
      "reason_codes": [
        { "layer": "attention", "polarity": "strength", "percentile": 88, "sample_confidence": "high" },
        { "layer": "postclick_messaging", "polarity": "strength", "percentile": 91, "sample_confidence": "high" },
        { "layer": "attributed_revenue", "polarity": "strength", "percentile": 74, "sample_confidence": "medium" }
      ]
    }
  ],
  "meta": {
    "profile_id": "uuid"
  }
}

Response fields

FieldTypeDescription
ad_external_idstringPlatform ad id (e.g. Meta ad id).
composite_scorenumber0–100, the cohort-normalized rule blend. null until the ad has been scored. The headline rank.
top_performer_likelihoodnumber0–1 probability — a likelihood, not a guarantee. Not ROAS, not lift — see the note above.
model_versionnumberThe ML ranker version that scored this ad, or null when score_source is rules.
score_sourcestringmodel (the ML ranker produced the likelihood) or rules (it fell back to composite_score).
maturity_stagestringcold · early · mature · calibrated — how settled the score is.
truth_gradestringpredicted (proxy signals only) · attributed (≥1 Atribu-attributed outcome of any kind) · lift (experiment-validated).
primary_outcome_kindstringThe headline outcome to show: cash · pipeline · messaging · meta (Meta's own attribution) · none.
cohort_*stringThe comparison cohort this ad was scored within, plus cohort_n_ads (cohort size).
hook_type / creative_format / cta_type / primary_angle / offersmixedCreative DNA — what to replicate.
attributed_revenue / roas / attributed_cash_outcomes / cacnumberAtribu-attributed cash (null/0 when none).
attributed_outcomes_total / attributed_pipeline_outcomes / attributed_pipeline_valuenumberAll Atribu-attributed conversions (any type); the pipeline subset (leads/appointments/closed-won) + its projected value (not cash).
meta_reported_conversions / meta_reported_conversion_valuenumberMeta's own reported per-ad conversions (last-click — not Atribu's chain; never sets truth_grade).
cost_per_conversation / messaging_conversations_started / first_reply_ratenumberMessaging-objective signals (the "cheap conversations" lens).
reason_codesarray{ layer, polarity: strength|weakness, percentile, sample_confidence: low|medium|high } — why it ranks.

Workspace-wide view

This endpoint is scoped to the API key's profile. The agency-wide cross-profile Top Performers (all clients in one ranked list, plus recurring creative patterns) is available through the Atribu MCP servertop_workspace_performers. See the MCP docs.

Scores build on a daily cadence

Top-performer scores rebuild once a day (independent of the latency-sensitive attribution recompute). A freshly connected Meta account needs one sync cycle before its ads appear here. An empty data array usually means "not scored yet", not "no top performers".

On this page