Readiness
One ordered checklist of what a profile still needs, and the single next thing to do about it.
GET /api/v1/profile/readinessScope: analytics:read
Everything a profile needs before ads, outcomes and attribution work end to end, as an ordered list of steps — and for every step that is not done, the one next action.
This is the read to make when a dashboard is empty and you need to say why.
Before it existed, answering that meant calling /connections,
/goals/definitions, /goals/outcome-counts, /exports/destinations,
/conversion-sync/legal, /quality/attribution and /profile/freshness and
reasoning about the result yourself.
Derived, never stored
There is no checklist table. Every step is computed at read time from the state
the rest of the product already keeps, so a connection that broke an hour ago
reads degraded on the next call, and a conversion definition you created a
second ago is reflected immediately. Nothing here is cached.
wizard_finished is not the answer to this question. It is the legacy
onboarding_completed boolean on GET /api/v1/profile, and it means exactly one
thing: a person pressed Finish in Atribu's own setup wizard. Every wizard step
is skippable, so it is not evidence that any step below is done — nothing in
summary is derived from it. Use it only to tell "has been through onboarding and
is still missing things" from "nobody has started".
Request
curl -H "Authorization: Bearer atb_live_YOUR_KEY" \
"https://api.atribu.app/api/v1/profile/readiness"import { Atribu } from "@atribu/node";
const atribu = new Atribu({ apiKey: "atb_live_YOUR_KEY" });
const { data } = await atribu.profile.readiness();
console.log(data.summary.next_step); // "capi_destination_enabled"import requests
res = requests.get(
"https://api.atribu.app/api/v1/profile/readiness",
headers={"Authorization": "Bearer atb_live_YOUR_KEY"},
)
data = res.json()["data"]There are no parameters. This is a property of the profile's configuration, not of a date range — the only clock involved is the tracker step's seven-day look-back, which is part of that step's definition.
Response
{
"data": {
"steps": [
{
"key": "attribution_enabled",
"status": "done",
"why": "Atribu's attribution pipeline is enabled for this profile.",
"next": null,
"docs_url": "https://www.atribu.app/docs/getting-started/overview"
},
{
"key": "ad_platform_connected",
"status": "degraded",
"why": "meta_ads is connected but its status is \"reconnect_required\" — it is not delivering spend or delivery data. Re-authorize it; the account itself is already linked, so this is a reconnect rather than a first connect.",
"next": { "handoff_kind": "connect" },
"docs_url": "https://www.atribu.app/docs/getting-started/connect-ads"
},
{
"key": "conversion_definitions_valid",
"status": "missing",
"why": "This profile has no conversion definition that is both revenue_type 'cash' and attribution_eligible, so nothing it records can ever produce a ROAS. Create one with POST /api/v1/goals/definitions; GET /api/v1/goals/definitions/suggestions proposes definitions from the outcome events already arriving.",
"next": { "method": "POST", "path": "/api/v1/goals/definitions" },
"docs_url": "https://www.atribu.app/docs/settings/goals"
}
],
"summary": { "done": 9, "total": 12, "next_step": "ad_platform_connected" },
"wizard_finished": true
},
"meta": { "profile_id": "your-profile-id" }
}steps is always all twelve steps, in golden-path order. A checklist that
omitted the steps it could not evaluate would have a length that varies by
profile, and done/total would stop meaning anything.
The four statuses
| status | meaning |
|---|---|
done | Satisfied. next is null. |
missing | Never configured. The ordinary next thing to do. |
degraded | Configured, and not working — a reconnect-required ad account is the canonical case. The fix is to re-connect, so a client that drew this as missing would tell someone to connect what they already connected. |
blocked | Cannot be satisfied by you at all, whatever you do. Today only attribution_enabled reaches it. |
Only done counts toward summary.done. degraded is not partial credit: a
destination that is configured and failing exports nothing, and a checklist that
scored it as progress would read 12/12 while the profile sends Meta nothing.
next — what to do about it
Every step that is not done carries a next, in one of two shapes.
{"method", "path"} is a call you can make right now with the credential you
already hold. The path is always one this API serves today, never a route that
is being built. Where a step's own write does not exist on v1 yet, the nearest
existing route is named and why says where the write actually happens.
{"handoff_kind"} is a class of action only a person can take:
| kind | why an agent cannot do it |
|---|---|
connect | An OAuth consent. It needs a browser and someone who can grant it. |
sign_dpa | A signature. One forged on a human's behalf is not a signature. |
checkout | A payment. |
contact_support | Atribu itself has to change something — see attribution_enabled below. |
A handoff_kind tells you what kind of hand-off is owed, not where: minting the
actual URL is a separate capability.
summary.next_step is the first non-done step in golden-path order, or
null when everything is done. First, not "most important" — the order is the
priority.
The steps
attribution_enabled
Whether the atribu_attribution entitlement is on for this profile. When it is
not, Atribu's whole pipeline — recompute, conversion extraction, automatic
events — is a deliberate no-op, so every other step can be finished and still
produce no attributed conversions.
Profiles created through a partner application deliberately do not hold this
entitlement. Such a profile answers blocked with contact_support, never an
empty checklist — the rest of the steps are still evaluated and still report
what they find, because "well configured" and "will never attribute anything" are
both facts you need.
tracker_installed
At least one tracking event reached Atribu in the last 7 days. missing
points at GET /api/v1/tracking/snippet; the GTM and Shopify-pixel variants are
at /api/v1/tracking/installers/gtm and
/api/v1/tracking/installers/shopify-pixel.
ad_platform_connected
A meta_ads or google_ads connection exists and is healthy (connected or
syncing). One healthy provider is enough — a working Meta connection beside a
broken Google one is done.
crm_or_outcome_source_connected
Something is telling Atribu when a lead, appointment or sale happens. Satisfied
by a healthy gohighlevel or shopify connection, or by outcome events
arriving through POST /api/v1/events — a system that posts its own outcomes
needs no CRM connection and no browser.
A connection that exists and is broken outranks the API-events fallback in the
why: an ERP that posted an event last month does not make a broken GoHighLevel
link fine.
payments_connected
A healthy stripe, mercadopago or shopify connection, or outcome events from
POST /api/v1/payments/webpay. Without one, no conversion can carry cash and
every ROAS on the profile is unmeasurable.
conversion_definitions_valid
At least one conversion_definitions row that is both revenue_type: "cash"
and attribution_eligible. Only cash counts toward ROAS — a profile whose
definitions are all pipeline records conversions that can never produce one.
GET /api/v1/goals/definitions/suggestions proposes definitions from the outcome
events already arriving.
attribution_windows_set
A profile_attribution_settings row exists. why says whether the windows are
explicit or Atribu's defaults (click 30 d, view-through 24 h, first-touch
90 d). Defaults are a legitimate answer, so both are done.
next names PATCH /api/v1/profile/attribution-settings (#1060), which writes
click_window_days, view_window_hours, first_touch_window_days and
cash_window_days directly and creates the row if it does not exist yet. The
same fields are editable in the Atribu console under Attribution.
first_conversion_attributed
At least one conversion has been credited to a touch. This is an outcome of
the steps above rather than a setting: finish them, then
POST /api/v1/attribution/recompute to re-project without waiting for the
scheduled run. GET /api/v1/quality/attribution shows how many conversions carry
a touch at all.
capi_destination_enabled · capi_rules_enabled
An enabled export destination, and at least one enabled signal rule. A
destination with no rules sends nothing, which is why they are two steps.
Destination and rule writes are not on this API yet; next names the reads that
show what is configured (GET /api/v1/exports/destinations,
GET /api/v1/ads/signals) and why says the writes happen in the Atribu console
under Conversion Sync.
legal_dpa
The Data Processing Agreement has been accepted.
GET /api/v1/conversion-sync/legal reads the full compliance record.
plan
done unless the workspace's plan limit is already spent. When active profiles
have reached max_active_profiles the step is degraded, not blocked: the
profile in hand keeps working, and what is refused is adding another one. A
workspace with no subscription row at all reads missing. An admin or
beta_tester override bypasses the limit and says so.
whatsapp_dataset_connected
Only meaningful for a profile with a WhatsApp Business account. It is done
for every profile without one — there is no click-to-WhatsApp traffic to
attribute, so there is nothing to wire.
With a WABA and no enabled WhatsApp dataset, it is missing: click-to-WhatsApp
conversions still ship, to the website pixel, where Meta cannot credit them to
the click-to-WhatsApp ad that produced them. next is a handoff rather than a
call — creating the dataset needs the customer's Meta token, and when Meta
withholds business_management a person has to paste the dataset id out of
Events Manager. GET /api/v1/exports/destinations reads back what is wired,
including each destination's data_source_kind.
What this response does not contain
No account ids, no pixel ids, no amounts, no PII. It says which providers are
connected, how many rules exist and which plan tier the workspace is on — which
is why it sits at analytics:read rather than a higher scope. A credential that
can read the dashboard can be told why the dashboard is empty.