---
title: "List armed message variants"
method: GET
path: "/campaigns/{campaign_id}/messages"
tags: ["campaigns"]
---

# List armed message variants

`GET /campaigns/{campaign_id}/messages`

## Request

- Base URL: `https://api.pscrpt.com/v1`
- URL: `https://api.pscrpt.com/v1/campaigns/{campaign_id}/messages`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `https://api.pscrpt.com/oauth/authorize`
    - Token URL: `https://api.pscrpt.com/oauth/token` scopes: `campaigns:read`

Armed variants as resolved; per-recipient rows live in `GET /v1/messages?filter[campaign_id]=`.

## Query parameters

- `page[limit]` integer
- `page[after]` string
- `sort` string
- `expand` string[]

## Headers

- `Postscript-Version` string, date

## Response `200`

One page of armed variants as resolved.

- object
  - `data` CampaignMessage[], required
    - `body` string, nullable, required: SMS/MMS/RCS text body, cut to its first 2,000 characters. Null for email and for RCS cards.
    - `channel` 'sms' | 'mms' | 'rcs' | 'email', required
    - `media_url` string, nullable, required: MMS image URL; null when the variant has none.
    - `message_key` string, required: Equals `node_id` for campaigns built outside this API, which carry no client-supplied key.
    - `node_id` string, required: Reporting handle — the `message_id` dimension in `POST /v1/message-stats` rows for this variant.
    - `object` 'campaign_message', required
    - `preview_text` string, nullable, required: Email preview text (preheader); null when unset or not email.
    - `queued_count` integer, nullable, required: Null until per-variant send counters are served; use `POST /v1/message-stats` grouped by `message`.
    - `sent_count` integer, nullable, required: Null until per-variant send counters are served; use `POST /v1/message-stats` grouped by `message`.
    - `split` number, nullable, required: Audience fraction; 1 for a variant under no split. Null when the enclosing split's weights are not readable.
    - `subject` string, nullable, required: Email subject line; null for other channels.
    - `template` Template: Mutable draft. Sends only ever reference immutable published versions (`tpv_`). Reads are authoritative (read-your-writes).
      - `archived_at` string, date-time
      - `channel` 'sms' | 'mms' | 'rcs' | 'email', required: Send channel — CLOSED per revision (`rcs` added 2026-07-30, D-18 amendment; RCS consent aliases `sms`, like `mms`). Channel and addressing mode are independent: `{channel: sms, to: {email: …}}` is valid — resolution finds the profile, the pipeline selects its phone; no identifier for the channel → rejected `invalid_destination`.
      - `content` union, required: Channel-shaped TAGGED value object (never a second content resource) — `channel` is the union tag: sms `{channel, text}` · mms `{channel, text, media_urls}` · rcs `{channel, text, media_urls?}` · email `{channel, subject, from_name?, html, text?}`. The tag must equal the template's `channel` (422 `unprocessable` otherwise).
        - SmsTemplateContent
          - `channel` 'sms', required: The union tag — must equal the template's `channel`.
          - `text` string, required: May contain merge tags (`{{ namespace.path }}`).
        - MmsTemplateContent
          - `channel` 'mms', required
          - `media_urls` string[], required: Media to attach, as URLs.
          - `text` string, required
        - RcsTemplateContent: RCS at v1 is text + optional media (the SMS-upgrade baseline). Rich RCS structures — cards, carousels, suggested actions — land ADDITIVELY on this shape (D-18 amendment 2026-07-30); they are never a separate content resource.
          - `channel` 'rcs', required
          - `media_urls` string[]: Optional media to attach, as URLs.
          - `text` string, required
        - EmailTemplateContent
          - `channel` 'email', required
          - `from_name` string, nullable
          - `html` string, required
          - `subject` string, required
          - `text` string, nullable: Optional plain-text alternative.
      - `created_at` string, date-time, required
      - `format` string, required: Open vocabulary (no constraining enum — additive values must validate). Provider-specific source is stored as provenance, never surfaced as canonical.
      - `id` string, required
      - `intended_use` 'marketing' | 'transactional', required: ADVISORY only — never the effective class; the publish-time attestation decides (D22).
      - `latest_version_id` string, nullable, required
      - `name` string, required
      - `object` 'template', required
      - `transactional_use_case_id` string, nullable, required: Reviewed use case — REQUIRED before publishing with `send_class: transactional`.
      - `updated_at` string, date-time, required
      - `variables` TemplateVariable[], required
        - `default` string, nullable: Fallback when no value is supplied.
        - `example` string, nullable
        - `name` string, required
        - `required` boolean
    - `template_version_id` string, nullable, required: Template version an email variant sends from; null for inline content. A template-armed variant follows its template's publishes, so this is the version sends use now. `expand=template` adds the sibling `template` object (the version's parent draft).
  - `meta` Meta, required
    - `as_of` string, date-time
    - `livemode` boolean, required
    - `page` PageMeta
      - `limit` integer, required
      - `next_cursor` string, nullable, required: Pass as `page[after]`. Null on the last page.
    - `request_id` string, required
    - `resolved_from` string: The merged-away profile ID the request addressed; `data` holds the survivor.
    - `revision` string, date, required

## Other responses

- `400`: Malformed input, an unknown parameter, an unsupported filter, sort, or expand, or a mistyped ID.
- `401`: Missing or invalid API key.
- `403`: The key lacks the required scope.
- `404`: No such resource in the authenticated property.
- `429`: Rate limit exceeded.
- `500`: Internal error.
- `502`: Upstream provider failure.
- `503`: Temporarily unavailable.

## Changes

- **2026-10-02** `c0c9a9f0ac5c`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/pscrpt/apis/postscript-native-api-beta/changes/campaigns/:campaign_id/messages/get.md)

---

[API](https://skmtc.dev/pscrpt/apis/postscript-native-api-beta.md) - [All operations](https://skmtc.dev/pscrpt/apis/postscript-native-api-beta/llms.txt) - [OpenAPI document](https://skmtc.dev/pscrpt/apis/postscript-native-api-beta/revisions/882458ee1f36?raw)
