The Wave campaign detail page (/campaigns/:id) is the per-event activation surface. It is tabbed, not a single flat page.

UI structure (reference FE)

EventHeader
└── Tabs
    ├── Wizard / OpenCampaigns   ← setup wizard, or existing campaigns
    └── Statistics               ← disabled when Meta stats unavailable
  • Taste clusters are handled inside the wizard’s Goals step (via suggested_tcs), not a dedicated /clusters panel on this page.
  • The Statistics tab’s KPIs come from the Meta integration endpoints, not /events/{eid}/statistics.

Prerequisites

  • An eid (from the Wave list).
  • An authenticated user with Permissions.wave.

The call chain

On mount (the primary loads):
#MethodPathPurpose
1GET/events/{eid}Event header.
2GET/setup_processes/{eid}Existing draft setup, or 404 if none.
3GET/events/{eid}/campaignsExisting campaigns (OpenCampaigns tab).
4GET/integrations/connect/facebook/statusMeta connection status (gates the wizard / Statistics).
5GET/events/{eid}/attribution_modelCurrent attribution model.
6GET/integrations/facebook/events/{eid}/campaign_resultsStatistics tab KPIs.
7GET/integrations/facebook/events/{eid}/fb_insightsImpressions / clicks / ad spend.
The reference FE does not call /events/{eid}/statistics here (the helper exists but is unused), does not render a /clusters panel on this page, and does not call /setup_processes/event_types on mount (that’s used inside the wizard’s ad-platform step). Meta auth status is /integrations/connect/facebook/statusnot /meta/authorization/status.

Entering the wizard

When the user starts setup, the wizard (not this page’s mount) calls the prefetch endpoints and Meta asset APIs (metaAssetsApi.listAssets, /setup_processes/event_types, …). See Campaigns lifecycle.

Editing published campaigns

The per-campaign PUT endpoints (/campaigns/{eid}/{tc}/{tc_run_id}/creative, .../target_audience, .../ignore) are not used by the current reference FE. Published-cluster edits go through POST /campaigns_setup. “Ignore” behaviour exists only in mocks.

Pause / optimisation / attribution toggles

These use query-string PUTs (matching the article’s general shape):
PUT /events/{eid}/client_campaign_status?client_campaign_status=PAUSED   # or RUNNING
PUT /events/{eid}/campaign_optimisation_status?campaign_optimisation_status=ON
PUT /events/{eid}/ad_campaign_optimisation_status?ad_campaign_optimisation_status=ON
PUT /events/{eid}/attribution_model     # body: { "model": "FD" | "META" | "EXTERNAL" }
Pause flow specifics in the reference FE:
  • The pause PUT returns 204.
  • Task status is read from data.state on the per-event task endpoint (GET /events/{eid}/client_campaign_status/task).
  • There is no continuous while + sleep polling loop — the FE does a single refresh fetch after the toggle.
export async function pauseEventCampaigns(eid: string) {
  await fd.put(`/events/${eid}/client_campaign_status?client_campaign_status=PAUSED`); // 204
  // Single refresh, not a polling loop:
  const task = await fd.get(`/events/${eid}/client_campaign_status/task`);
  return task.state;   // SUCCESS | FAILURE | PENDING | STARTED
}

Reference implementation (read shell)

export function WaveCampaignDetail({ eid }: { eid: string }) {
  const event     = useFd(`/events/${eid}`);
  const setupProc = useFd(`/setup_processes/${eid}`, {
    onError: (e) => (e.status === 404 ? null : Promise.reject(e)),  // 404 ⇒ no draft
  });
  const campaigns = useFd(`/events/${eid}/campaigns`);
  const metaConn  = useFd("/integrations/connect/facebook/status");
  const results   = useFd(`/integrations/facebook/events/${eid}/campaign_results`);

  return (
    <>
      <EventHeader event={event.data} />
      <Tabs>
        <Tab label={setupProc.data ? "Campaigns" : "Set up"}>
          {setupProc.data
            ? <OpenCampaigns campaigns={campaigns.data} />
            : <SetupWizard eid={eid} metaConnected={metaConn.data?.connected} />}
        </Tab>
        <Tab label="Statistics" disabled={!results.data}>
          <EventStatistics results={results.data} />
        </Tab>
      </Tabs>
    </>
  );
}

Gotchas

EventHeader + tabs (wizard/OpenCampaigns, Statistics). No standalone clusters panel.
Not /meta/authorization/status.
Not /events/{eid}/statistics (unused on this page).
Published edits use POST /campaigns_setup; “ignore” is mock-only.
No continuous polling loop; one GET .../client_campaign_status/task after the PUT, reading data.state.
Means no draft yet — show the “Set up” CTA.