Skip to main content

Campaigns

A Campaign is a time-bounded grouping of missions, typically for promotions ("Spring Sale 2026", "Onboarding Week"). Campaigns let you:

  • Ship a set of related missions atomically.
  • Apply a consistent visual theme (primaryColor, banner image).
  • Time-box availability via startAt / endAt.
interface Campaign {
id: string;
title: string;
description: string;
startAt: number;
endAt: number;
missionIds: string[];
theme?: CampaignTheme;
bannerUrl?: string;
}

Active window

GET /v1/campaigns filters to campaigns where endAt >= now (active or upcoming, ordered by startAt). Pass ?include=expired to retrieve historical campaigns for archival or replay UIs.

┌─────── start_at ───────┐ ┌─── end_at ───┐
│ │ │ │
│ upcoming (returned │ active │ expired │
│ if startAt > now) │ (returned) │ (returned │
│ │ │ only with │
│ │ │ ?include= │
│ │ │ expired) │
└────────────────────────┘ └──────────────┘


Date.now()

Composition

A campaign references missions via missionIds. Missions can belong to at most one campaign (the relationship lives on Mission.campaignId). GET /v1/campaigns/:id?include=missions hydrates the mission rows in one round-trip.

Theming

CampaignTheme.primaryColor lets a campaign override the global --color-qk-primary token for the duration of its run, giving the <CampaignBanner> and downstream widgets a campaign-specific accent without rebuilding your app.