# Campaigns API reference

> Canonical HTML: https://screenrig.ai/docs/api/campaigns
> Source SHA-256: e0c997a2ab813502f0d99a41d2ed1d3d6b26dbaf1a3d7e514c1cce0278ff8422

Campaigns. This group has 10 operations, each with its authentication, parameters, request body fields, request template and responses. The [API overview](https://screenrig.ai/docs/api.md) covers services, authentication, requests and retries, problem codes and versioning.

Replace uppercase placeholders. Save a schema-valid JSON body in request.json when required. Cookie examples use a local cookie jar from an authenticated session.

## Campaigns

### GET /api/campaigns

**List Campaigns**

Lists the project's campaigns in precedence order (at most 100), the order resolution reads them. reserved is present on every campaign.

A caller limited to screens (docs/screen-scope.md) sees every campaign, with editable true only when the whole audience is inside its scope (a tag leaf and the root every-screen rule never are; an all rule needs one contained child, an any rule every child) and the caller may change what plays.


Operation: listCampaigns.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The project's campaigns. | CampaignList (application/json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/campaigns

**Create Campaign**

Creates a campaign: every screen in its audience switches to playlist_id while from, until and windows hold in the screen's timezone (screenrig.schedule/v1; omit all three for always), and back when they stop holding.

A screen resolves its playlist as its takeover, then the first campaign that applies in precedence order (priority, higher first, then the most recently created), then its playlist schedule, then its default playlist. A campaign applies only to a screen with a default playlist; one with from, until or windows needs the screen's timezone.

The playlist must exist and be approved (playlist_not_approved). Screens switch within a minute; GET /api/campaigns/{id}/screens shows each screen's standing. An organization has at most 100 campaigns across its projects (campaign_limit_reached).

Appends campaign.created. reserved true reserves the campaign, and only a person who can approve sets it (reserved_item for an agent, a service client or anyone else), appending campaign.reserved_changed.

A caller limited to screens (docs/screen-scope.md) creates a campaign only for an audience inside its scope (folder and screen_id leaves; no tag, no every screen), else outside_screen_scope, and only as a person who can approve (approver_required).

A campaign whose audience reaches a protected screen is a protected_change review decided by a second approver (202 pending_review) at every access level. reserved true is protected folders and paused true on a new campaign (a draft) is schedule change control, both part of the Enterprise plan; a project whose plan lacks it is refused with feature_not_in_plan (402).


Operation: createCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: CampaignWrite

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| name | required | string | minLength: 1 maxLength: 120 |
| playlist_id | required | string | minLength: 1 |
| audience | required | CampaignAudience | Which screens a campaign targets: exactly one of all (every rule matches), any (at least one matches), tag (the screen carries the tag), screen_id (that screen) or folder (the screens in that screen folder and every folder inside it, GET /api/screen-folders; the folder must exist). Rules nest at most 3 deep and an audience has at most 500 rules. {"all": []} is every screen of the project; elsewhere all and any list at least one rule. |
| from | optional | string | pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T([01][0-9]\|2[0-3]):[0-5][0-9]$" |
| until | optional | string | Later than from. pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T([01][0-9]\|2[0-3]):[0-5][0-9]$" |
| windows | optional | array |  |
| monthly | optional | array |  |
| dates | optional | array |  |
| except | optional | array | Civil dates, stored ascending and once each. An exception removes every occurrence its date starts, overnight tails included; it falls between from and until. |
| data | optional | PageDataCondition | A card-data predicate, evaluated before civil time. Missing or expired data never matches. The page also respects its ordinary time bounds. Requires host capability page.conditions; older hosts receive the page disabled. |
| interaction | optional | LevelInteraction | The level holds while someone is using the screen: from a touch, click or key until idle_s seconds pass with no input. Typical use: an interactive page above an attract loop. idle_s is stored and returned (60 when omitted). |
| covers | optional | string | Where the level plays: the full page (default, stored absent) or main, the page itself, for an ordinary playlist; header, footer or side, a strip drawn over the page, for a region playlist of that region only (PlaylistRegionFormat). A region playlist is refused with full or main, and a strip needs a region playlist that is laid out on a targeted display. Allowed: "full", "main", "header", "footer", "side" |
| displays | optional | array | The outputs of a video wall it plays on; absent plays on every output. |
| start | optional | string | on_time switches at the edge, interrupting the current item; next_item (default, stored absent) waits for it to end. Allowed: "next_item", "on_time" |
| priority | optional | integer | default: 0 minimum: 0 maximum: 100 |
| paused | optional | boolean | default: false |
| reserved | optional | boolean | Only a person who can approve reserves a campaign (reserved_item otherwise). default: false |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://api.screenrig.ai/api/campaigns'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 201 | Created. | Campaign (application/json); headers: ETag |
| 400 | invalid_request, including an audience rule, a window or a playlist_id the project does not have. | Problem (application/problem+json) |
| 402 | feature_not_in_plan — Protected folders and schedule change control are part of the Enterprise plan; the problem names the feature, the plan the account is on and required_plan. A campaign that locks a playlist to display 2 or beyond of a video wall (displays) is part of Plus. The problem names the feature, the project's plan and required_plan. | Problem (application/problem+json) |
| 409 | campaign_limit_reached, playlist_not_approved or idempotency_mismatch. | Problem (application/problem+json) |
| 202 | The write became a review and waits for a person's approval (docs/reviews.md), under Propose access, or at any access level when it reaches a screen in a protected screen folder, where a second approver decides it (docs/screen-scope.md). A person approves, rejects or requests changes in the dashboard at review.url. An Idempotency-Key replay answers the same body. | ReviewPending (application/json) |
| 403 | outside_screen_scope or approver_required as on ScreenScopePlays, or reserved_item - a reserved campaign is changed, paused, deleted or un-reserved only by a person who can approve reviews, never by an agent or a service client (docs/screen-scope.md). | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/campaigns/preview

**Preview Campaign**

What a campaign write would change, without making it. With id, body is the PATCH body of that campaign; without, it is the POST body of a new one. The body is checked as the write checks it (an audience rule, a window, an unapproved playlist, a screen folder the project does not have).

The answer lists the screens that would gain the campaign on their stack and those that would lose it (count, and the first 500 screen ids), and the schedule calendar of the screens in the old and the new audience as it is (before) and as it would be (after) over from to to (default: a week from now; at most 93 days), grouped as GET /api/schedule/calendar groups.

A paused campaign is on no stack, so publishing one gains its audience; an edit that keeps the campaign on a screen's stack gains and loses nothing and shows in the calendars. Read access: nothing is written.


Operation: previewCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: CampaignPreviewRequest

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| id | optional | string | The campaign a PATCH body is previewed on; omit to preview a create. |
| body | required | object | A CampaignPatch with id, a CampaignWrite without. |
| from | optional | string | Start of the calendars; defaults to now. format: "date-time" |
| to | optional | string | End of the calendars; defaults to a week after from, at most 93 days after it. format: "date-time" |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://api.screenrig.ai/api/campaigns/preview'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The preview. | SchedulePreview (application/json) |
| 400 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 404 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 409 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /api/campaigns/{id}

**Get Campaign**

One campaign. reserved is always present; editable is present for a caller limited to screens (see listCampaigns).


Operation: getCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | One campaign. | Campaign (application/json); headers: ETag |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### PATCH /api/campaigns/{id}

**Update Campaign**

Changes the members the body sets; null clears from, until or windows. paused true stops the campaign on every screen and false resumes it. A paused campaign is a draft: it is on no screen's stack, and a write that leaves it paused re-resolves no screen.

Publishing it for a test is this PATCH with paused false and an audience that is a test folder or a few screens; POST /api/campaigns/{id}/promote then copies that audience onto the real one. Every screen of the old and the new audience re-resolves within a minute. Appends campaign.updated. If-Match guards the revision.

Each write is stored in the campaign's history (GET /api/campaigns/{id}/revisions). campaign.updated. If-Match guards the revision. reserved sets or clears the reserved flag (a reserved campaign is changed, paused or un-reserved only by a person who can approve: reserved_item otherwise); a flip appends campaign.reserved_changed.

A caller limited to screens (docs/screen-scope.md) changes a campaign only when its stored and new audience are inside its scope (outside_screen_scope; otherwise it is read-only to them).

A campaign that reaches a protected screen is a protected_change review decided by a second approver (202 pending_review). reserved true on a campaign that is not reserved is protected folders, which the Enterprise plan includes; a project whose plan lacks it is refused with feature_not_in_plan (402).

Pausing or resuming a campaign, and editing or releasing a reserved one, are open on every plan.


Operation: updateCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: CampaignPatch

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| name | optional | string | minLength: 1 maxLength: 120 |
| playlist_id | optional | string | minLength: 1 |
| audience | optional | CampaignAudience | Which screens a campaign targets: exactly one of all (every rule matches), any (at least one matches), tag (the screen carries the tag), screen_id (that screen) or folder (the screens in that screen folder and every folder inside it, GET /api/screen-folders; the folder must exist). Rules nest at most 3 deep and an audience has at most 500 rules. {"all": []} is every screen of the project; elsewhere all and any list at least one rule. |
| from | optional | inline | null clears it. |
| until | optional | inline | null clears it. |
| windows | optional | inline | null clears them. |
| monthly | optional | inline | null clears them. |
| dates | optional | inline | null clears them. |
| except | optional | inline | null clears them. |
| data | optional | inline | null clears it. |
| interaction | optional | inline | null clears it. |
| covers | optional | inline | null is the full page. header, footer and side need a region playlist of that region (PlaylistRegionFormat). |
| displays | optional | inline | null plays on every output. |
| start | optional | inline | null is next_item. |
| priority | optional | integer | minimum: 0 maximum: 100 |
| paused | optional | boolean |  |
| reserved | optional | boolean | Only a person who can approve reserves or releases a campaign (reserved_item otherwise). |

#### Request template

~~~sh
curl --request PATCH --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The updated campaign. | Campaign (application/json); headers: ETag |
| 402 | feature_not_in_plan — Protected folders are part of the Enterprise plan; the problem names the feature, the plan the account is on and required_plan. Setting displays other than the campaign's own is part of Plus; null clears it in every plan. The problem names the feature, the project's plan and required_plan. | Problem (application/problem+json) |
| 409 | playlist_not_approved or idempotency_mismatch. | Problem (application/problem+json) |
| 412 | revision_conflict. | Problem (application/problem+json) |
| 202 | The write became a review and waits for a person's approval (docs/reviews.md), under Propose access, or at any access level when it reaches a screen in a protected screen folder, where a second approver decides it (docs/screen-scope.md). A person approves, rejects or requests changes in the dashboard at review.url. An Idempotency-Key replay answers the same body. | ReviewPending (application/json) |
| 403 | outside_screen_scope or approver_required as on ScreenScopePlays, or reserved_item - a reserved campaign is changed, paused, deleted or un-reserved only by a person who can approve reviews, never by an agent or a service client (docs/screen-scope.md). | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### DELETE /api/campaigns/{id}

**Delete Campaign**

Deletes the campaign and its revision history. Every screen showing it returns to what it would show without it within a minute. Appends campaign.deleted. If-Match guards the revision. A reserved campaign is deleted only by a person who can approve (reserved_item).

A caller limited to screens (docs/screen-scope.md) deletes a campaign only when its audience is inside its scope (outside_screen_scope). A campaign that reaches a protected screen is a protected_change review decided by a second approver (202 pending_review).


Operation: deleteCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request template

~~~sh
curl --request DELETE --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 204 | Deleted. | no body |
| 412 | revision_conflict. | Problem (application/problem+json) |
| 202 | The write became a review and waits for a person's approval (docs/reviews.md), under Propose access, or at any access level when it reaches a screen in a protected screen folder, where a second approver decides it (docs/screen-scope.md). A person approves, rejects or requests changes in the dashboard at review.url. An Idempotency-Key replay answers the same body. | ReviewPending (application/json) |
| 403 | outside_screen_scope or approver_required as on ScreenScopePlays, or reserved_item - a reserved campaign is changed, paused, deleted or un-reserved only by a person who can approve reviews, never by an agent or a service client (docs/screen-scope.md). | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /api/campaigns/{id}/revisions

**List Campaign Revisions**

The campaign's revisions, newest first: the campaign as stored after each write by a person, an agent or a schedule import (a create, an update, a promote, a restore), with the kind of change and who made it.

History begins with the revision a campaign held when revision history was first recorded: until its next write the list holds that revision alone, with change baseline. A campaign whose history holds no revision with paused false is a draft. Revisions are kept for as long as the campaign is and go with it.

At most 50 per page; next_cursor while more remain, null on the last page.


Operation: listCampaignRevisions.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| after | query | optional | next_cursor of the previous page of the same list, with the same filters. Omitted starts at the newest row. A value that is not such a cursor is invalid_request. |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID/revisions'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The campaign's revisions, newest first. | CampaignRevisionList (application/json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/campaigns/{id}/revisions/{revision}/restore

**Restore Campaign Revision**

Makes an earlier revision current again by copying it forward through the same write as PATCH: its name, playlist, audience, rule, placement, priority and paused become a new revision (change restored, restored_from the revision copied), checked as an update is (its playlist must still exist and be approved), and every screen of the old and the new audience re-resolves, unless the campaign was paused and stays paused.

Earlier revisions stay as they were. If-Match is required and names the current revision (invalid_request when absent, revision_conflict when stale). A revision whose content is the current content changes nothing and answers the current campaign. The same access as PATCH.


Operation: restoreCampaignRevision.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| revision | path | required | A revision of the record, as its revisions list numbers them. |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID/revisions/REVISION/restore'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The campaign with the copied revision current; ETag carries its revision. | Campaign (application/json); headers: ETag |
| 404 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 409 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 412 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### POST /api/campaigns/{id}/promote

**Promote Campaign**

Publishes a test. A test publish is a PATCH of a draft with paused false and an audience that is a test folder or a few screens; promote then copies the audience of revision (the draft's own, paused, revision) onto the campaign in one write (change promoted, restored_from the revision copied) and every screen of the old and the new audience re-resolves.

Refused (invalid_request, naming revision) when that revision was not paused, since it is not a draft, and when the campaign is paused now, since there is no test to promote. If-Match is required and names the current revision. A revision whose audience is the current one changes nothing. The same access as PATCH.

Promote is schedule change control, which the Enterprise plan includes; a project whose plan lacks it is refused with feature_not_in_plan (402). Revision history, restore and previews are open on every plan.


Operation: promoteCampaign.

- Authentication: projectBearer OR dashboardSession
- Request body: CampaignPromote

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| If-Match | header | optional | Optional positive resource revision. Omit to write the current resource; a supplied stale revision is revision_conflict. |
| Idempotency-Key | header | optional | Omit for a fresh operation. Supply and reuse a key to deduplicate retries; the CLI manages keys automatically. |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| revision | required | integer | The draft's (paused) revision whose audience the campaign takes. minimum: 1 |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID/promote'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The campaign with the draft's audience; ETag carries its revision. | Campaign (application/json); headers: ETag |
| 402 | feature_not_in_plan — Schedule change control is part of the Enterprise plan; the problem names the feature, the plan the account is on and required_plan. | Problem (application/problem+json) |
| 404 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 409 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 412 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /api/campaigns/{id}/screens

**List Campaign Screens**

The campaign's reach. counts covers every live screen in its audience (audience, then one count per status); items is one page of those screens in screen id order with the campaign's standing on each (see CampaignStatus).

A caller limited to screens (docs/screen-scope.md) sees and counts only the audience screens inside its scope; counts and paging cover that set.


Operation: listCampaignScreens.

- Authentication: projectBearer OR dashboardSession
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| id | path | required |  |
| limit | query | optional |  |
| cursor | query | optional | next_cursor of the previous page. |

#### Request template

~~~sh
curl --request GET --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --cookie cookies.txt --cookie-jar cookies.txt 'https://api.screenrig.ai/api/campaigns/RESOURCE_ID/screens'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | The campaign's audience and standing. | CampaignScreens (application/json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |


## Sitemap

See the [public documentation sitemap](https://screenrig.ai/sitemap.md).
