2.8 KiB
Campaigns API
Base path: /api/v1/campaigns
All endpoints require Authorization: Bearer <jwt>.
Related: 08 - Campaigns, 07 - Render Engine, 04 - Database Schema
GET /campaigns
List all campaigns for the current team, ordered by startAt descending (most recent first).
Minimum role: Any authenticated team member
Response: CampaignSummary[]
[
{
"id": "cuid",
"name": "Summer Sale 2026",
"startAt": "2026-06-01T00:00:00.000Z",
"endAt": "2026-08-31T23:59:59.000Z",
"status": "active"
}
]
| Field | Type | Notes |
|---|---|---|
id |
string | cuid |
name |
string | Display name of the campaign |
startAt |
ISO datetime | Campaign window start (inclusive) |
endAt |
ISO datetime | null | Campaign window end (inclusive). null means open-ended |
status |
string | Free-form status string, default "active". Must be exactly "active" (lowercase) for the campaign to be treated as active — see warning below. |
Warning:
Campaign.statusis a free-formStringcolumn with no enum constraint. TheDESC_OUTDATED_SPONSOR_COPYlint rule checksstatus !== 'active'(exact lowercase match). Any other value —"ACTIVE","paused","inactive","disabled", or any typo — is treated as inactive: the campaign's blocks are excluded from rendering and all videos referencing them receive a lint ERROR. There is no input validation at the API or DB level. See the backlog.
Note: The full
notesfield and the linkedblocksrelation are not included in this response. Campaigns are read here for display and for populating dropdowns when assigning blocks to a campaign. Full campaign management (create, update, delete, assign blocks) is not exposed via the REST API — it is managed directly in the database or through future admin tooling.
How campaigns affect rendering
Campaign blocks are CAMPAIGN-type DescriptionBlock rows linked to a campaign via campaignId. At render time, the engine checks whether startAt ≤ now ≤ endAt for each linked campaign. If the window is active, all of that campaign's blocks are automatically appended to the rendered description — regardless of whether they appear in the video's blockOrder. If the window is inactive, they are silently omitted.
This is the only block type that bypasses blockOrder. See 07 - Render Engine for the full rendering pipeline.
Current limitations
Campaign CRUD (create, update, delete) and block assignment are not yet exposed through the API. The GET /campaigns endpoint exists to allow the frontend to display campaign names and populate selectors. Full campaign management requires direct database access or a future admin interface. See Campaign CRUD API in 01 - Technical Debt and Future Work.