> ## Documentation Index
> Fetch the complete documentation index at: https://developers.redo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Campaign

> A one-off marketing send to a set of segments, on a single channel.

**Required scopes:** [`campaigns_read`](/docs/api-reference/v3/reference/scopes#scope-campaigns_read), [`campaigns_write`](/docs/api-reference/v3/reference/scopes#scope-campaigns_write)

<ResponseField name="analytics" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-analytics">CampaignAnalytics!</a>} required>
  Analytics for this campaign, grouped by what is being measured.

  <Expandable title="fields" lazyRender>
    <ResponseField name="messaging" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-messaging-analytics">CampaignMessagingAnalytics!</a>} required>
      Email and SMS performance, read from the analytics warehouse: what was sent, how it was engaged with, and the orders and revenue attributed to it.

      **Requires:** [`campaigns_analytics_read`](/docs/api-reference/v3/reference/scopes#scope-campaigns_analytics_read)

      <Expandable title="fields" lazyRender>
        **Arguments**

        <ResponseField name="attributionWindowDays" type="Int">
          How many days after a message an order still counts toward it, 1-30.
        </ResponseField>

        <ResponseField name="endDate" type={<a href="/docs/api-reference/v3/reference/common/date">Date!</a>} required>
          Last day to report on, inclusive, in the store's timezone. The range may span at most 400 days.
        </ResponseField>

        <ResponseField name="startDate" type={<a href="/docs/api-reference/v3/reference/common/date">Date!</a>} required>
          First day to report on, inclusive, in the store's timezone. Must be on or before `endDate`, and the range may span at most 400 days.
        </ResponseField>

        **Fields**

        <ResponseField name="series" type={<a href="/docs/api-reference/v3/reference/marketing/message-analytics-point">[MessageAnalyticsPoint!]!</a>} required>
          One entry per day with activity, oldest first. Quiet days are omitted rather than reported as zero.
        </ResponseField>

        <ResponseField name="totals" type={<a href="/docs/api-reference/v3/reference/marketing/message-analytics-totals">MessageAnalyticsTotals!</a>} required>
          Totals across the whole range. A campaign with no activity reports zero counts and null rates.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="canceledAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
  When the merchant canceled the campaign, if they did.
</ResponseField>

<ResponseField name="channel" type={<a href="/docs/api-reference/v3/reference/marketing/marketing-channel">MarketingChannel!</a>} required>
  The channel this campaign sends on.
</ResponseField>

<ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
  When the campaign was created.
</ResponseField>

<ResponseField name="emailVariants" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-email-variant">[CampaignEmailVariant!]!</a>} required>
  The email content this campaign sends, oldest arm first. A campaign that is not split-testing has exactly one entry; there is no separate `subject` on the campaign because a split test has more than one.

  <Expandable title="fields" lazyRender>
    <ResponseField name="abTestWeight" type="Float!" required>
      The share of recipients this variant was sent to. A campaign with a single variant weights it 1.
    </ResponseField>

    <ResponseField name="position" type="Int!" required>
      This variant's position within the campaign, starting at 0. Stable, so it names an arm of a split test across reports.
    </ResponseField>

    <ResponseField name="template" type={<a href="/docs/api-reference/v3/reference/marketing/email-template">EmailTemplate</a>}>
      The content this variant sent. Null when the template has since been deleted.

      **Requires:** [`marketing_templates_read`](/docs/api-reference/v3/reference/scopes#scope-marketing_templates_read)

      <Expandable title="fields" lazyRender>
        <ResponseField name="contentBackgroundColor" type="String!" required>
          The content canvas background, as set under Email styles in the email builder.
        </ResponseField>

        <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
          When the template was created.
        </ResponseField>

        <ResponseField name="emailBackgroundColor" type="String!" required>
          The email background, as set under Email styles in the email builder.
        </ResponseField>

        <ResponseField name="id" type="ID!" required>
          The id of this template.
        </ResponseField>

        <ResponseField name="legacyId" type="String!" required>
          The template's legacy Mongo ObjectId (24-char hex) from before the CockroachDB migration.
        </ResponseField>

        <ResponseField name="linkColor" type="String">
          The default link color, as set under Email styles in the email builder. Null when the merchant left it unset.
        </ResponseField>

        <ResponseField name="name" type="String!" required>
          The merchant-facing name of the template.
        </ResponseField>

        <ResponseField name="preview" type={<a href="/docs/api-reference/v3/reference/marketing/email-template-preview">EmailTemplatePreview</a>}>
          Render this template, to see what recipients get. Use a width of about 375 for a phone.

          **Requires:** [`marketing_templates_read`](/docs/api-reference/v3/reference/scopes#scope-marketing_templates_read)

          <Expandable title="fields" lazyRender>
            **Arguments**

            <ResponseField name="eventId" type="ID">
              Render with this recent event's data instead of sample data: a 24-character hex event id. A well-formed id that can't be found falls back to sample data.
            </ResponseField>

            <ResponseField name="width" type="Int">
              Viewport width of the screenshot, 320-1200 pixels.
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="previewText" type="String">
          The preview text shown after the subject in an inbox. Null when the merchant left it unset.
        </ResponseField>

        <ResponseField name="sections" type={<a href="/docs/api-reference/v3/reference/marketing/email-template-section">[EmailTemplateSection!]!</a>} required>
          The blocks that make up the email body, in order. Nested column children keep their own ids. A type this API version does not model field-by-field is returned as EmailTemplateUnknownSection.
        </ResponseField>

        <ResponseField name="sectionsJson" type={<a href="/docs/api-reference/v3/reference/common/json">[JSON!]!</a>} required>
          `sections` with every field selected, as JSON: one element per root block, in order, with `__typename` and nested column children. Empty or unreadable stored sections are \[]. Edits go through operations.
        </ResponseField>

        <ResponseField name="subject" type="String!" required>
          The subject line **as authored**, before per-recipient substitution. A subject containing `{{ }}` placeholders is filled in per customer at send time, and some sends prepend a prefix, so this is not necessarily the subject any one customer saw. Empty when the template has no subject of its own.
        </ResponseField>

        <ResponseField name="trigger" type={<a href="/docs/api-reference/v3/reference/marketing/marketing-trigger">MarketingTrigger!</a>} required>
          The trigger context this template is valid for. Immutable after create. UNKNOWN when the stored trigger is not modeled in this API version.
        </ResponseField>

        <ResponseField name="updatedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
          When the template was last edited. Templates stay editable after the campaigns that used them have finished, so compare this against a campaign's `finishedAt` to tell whether the content here is still what that campaign actually sent.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="errorCode" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-error-code">CampaignErrorCode</a>}>
  Why the campaign failed, when it did.
</ResponseField>

<ResponseField name="excludedSegments" type={<a href="/docs/api-reference/v3/reference/marketing/segment">[Segment!]!</a>} required>
  The segments held out of this campaign.

  **Requires:** [`segments_read`](/docs/api-reference/v3/reference/scopes#scope-segments_read)

  <Expandable title="fields" lazyRender>
    <ResponseField name="conditions" type={<a href="/docs/api-reference/v3/reference/common/json">JSON</a>}>
      Dynamic segment condition tree. Null for static and persona segments.
    </ResponseField>

    <ResponseField name="countsRefreshedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
      When the member counts were last recalculated. They are not live.
    </ResponseField>

    <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the segment was created.
    </ResponseField>

    <ResponseField name="description" type="String">
      The merchant's description of who this segment is for.
    </ResponseField>

    <ResponseField name="emailSubscriberCount" type="Int">
      Members subscribed to email marketing as of `countsRefreshedAt`.
    </ResponseField>

    <ResponseField name="id" type="ID!" required>
      The id of this segment.
    </ResponseField>

    <ResponseField name="legacyId" type="String!" required>
      The segment's legacy Mongo ObjectId (24-char hex) from before the CockroachDB migration.
    </ResponseField>

    <ResponseField name="memberCount" type="Int">
      Customers in the segment as of `countsRefreshedAt`. Null until it has first been counted.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The merchant-facing name of the segment.
    </ResponseField>

    <ResponseField name="smsSubscriberCount" type="Int">
      Members subscribed to SMS marketing as of `countsRefreshedAt`.
    </ResponseField>

    <ResponseField name="type" type={<a href="/docs/api-reference/v3/reference/marketing/segment-type">SegmentType!</a>} required>
      How membership of this segment is determined.
    </ResponseField>

    <ResponseField name="updatedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the segment was last updated.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="failedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
  When the campaign failed to send, if it did.
</ResponseField>

<ResponseField name="followUpConfig" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-follow-up-config">CampaignFollowUpConfig</a>}>
  Follow-up email configuration when one was enabled.

  <Expandable title="fields" lazyRender>
    <ResponseField name="delayMs" type="Float">
      Delay after the original send before the follow-up goes out.
    </ResponseField>

    <ResponseField name="enabled" type="Boolean!" required>
      Whether a follow-up send is configured.
    </ResponseField>

    <ResponseField name="engagementPeriod" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-follow-up-engagement-period">CampaignFollowUpEngagementPeriod</a>}>
      Engagement window, in days, used to pick recipients.
    </ResponseField>

    <ResponseField name="originalCampaignLegacyId" type="String">
      Legacy Mongo ObjectId of the campaign this follow-up was created from.
    </ResponseField>

    <ResponseField name="subjectLine" type="String">
      Subject line for the follow-up email.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="fromAddress" type={<a href="/docs/api-reference/v3/reference/marketing/email-address">EmailAddress</a>}>
  The from address recorded when the campaign sent. Null for drafts and for SMS campaigns.

  <Expandable title="fields" lazyRender>
    <ResponseField name="email" type="String!" required>
      The mailbox address.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The display name shown alongside the address.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="fromSender" type={<a href="/docs/api-reference/v3/reference/marketing/email-sender">EmailSender</a>}>
  The From mailbox chosen for this campaign. Null when the store default should be used, and for SMS.

  **Requires:** [`campaigns_read`](/docs/api-reference/v3/reference/scopes#scope-campaigns_read)

  <Expandable title="fields" lazyRender>
    <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the address was added.
    </ResponseField>

    <ResponseField name="email" type="String!" required>
      The mailbox address.
    </ResponseField>

    <ResponseField name="id" type="ID!" required>
      The id of this sender address. Pass it to `updateCampaign`.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The display name shown alongside the address.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="id" type="ID!" required>
  The id of this campaign.
</ResponseField>

<ResponseField name="legacyId" type="String!" required>
  The campaign's legacy Mongo ObjectId (24-char hex) from before the CockroachDB migration.
</ResponseField>

<ResponseField name="name" type="String!" required>
  The merchant-facing name of the campaign.
</ResponseField>

<ResponseField name="replyToAddress" type={<a href="/docs/api-reference/v3/reference/marketing/email-address">EmailAddress</a>}>
  The reply-to address recorded when the campaign sent. Null when none was set.

  <Expandable title="fields" lazyRender>
    <ResponseField name="email" type="String!" required>
      The mailbox address.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The display name shown alongside the address.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="replyToSender" type={<a href="/docs/api-reference/v3/reference/marketing/email-sender">EmailSender</a>}>
  The Reply-To mailbox chosen for this campaign. Null when the store default should be used.

  **Requires:** [`campaigns_read`](/docs/api-reference/v3/reference/scopes#scope-campaigns_read)

  <Expandable title="fields" lazyRender>
    <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the address was added.
    </ResponseField>

    <ResponseField name="email" type="String!" required>
      The mailbox address.
    </ResponseField>

    <ResponseField name="id" type="ID!" required>
      The id of this sender address. Pass it to `updateCampaign`.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The display name shown alongside the address.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="scheduledAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
  When the campaign is scheduled to start sending. Null for drafts, and for campaigns scheduled in each recipient's local time.
</ResponseField>

<ResponseField name="scheduledAtTimeZone" type="String">
  IANA time zone the merchant picked when scheduling a single UTC instant. Null for drafts and local-time sends.
</ResponseField>

<ResponseField name="scheduledLocalFallbackTimeZone" type="String">
  IANA time zone used when a recipient has no time zone, for local-time sends. Null when `scheduledAt` is set.
</ResponseField>

<ResponseField name="scheduledLocalTime" type="String">
  For campaigns scheduled in each recipient's local time, the wall-clock time they send at, as `YYYY-MM-DDTHH:mm:ss`. Null when `scheduledAt` is set.
</ResponseField>

<ResponseField name="segments" type={<a href="/docs/api-reference/v3/reference/marketing/segment">[Segment!]!</a>} required>
  The segments this campaign was sent to.

  **Requires:** [`segments_read`](/docs/api-reference/v3/reference/scopes#scope-segments_read)

  <Expandable title="fields" lazyRender>
    <ResponseField name="conditions" type={<a href="/docs/api-reference/v3/reference/common/json">JSON</a>}>
      Dynamic segment condition tree. Null for static and persona segments.
    </ResponseField>

    <ResponseField name="countsRefreshedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
      When the member counts were last recalculated. They are not live.
    </ResponseField>

    <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the segment was created.
    </ResponseField>

    <ResponseField name="description" type="String">
      The merchant's description of who this segment is for.
    </ResponseField>

    <ResponseField name="emailSubscriberCount" type="Int">
      Members subscribed to email marketing as of `countsRefreshedAt`.
    </ResponseField>

    <ResponseField name="id" type="ID!" required>
      The id of this segment.
    </ResponseField>

    <ResponseField name="legacyId" type="String!" required>
      The segment's legacy Mongo ObjectId (24-char hex) from before the CockroachDB migration.
    </ResponseField>

    <ResponseField name="memberCount" type="Int">
      Customers in the segment as of `countsRefreshedAt`. Null until it has first been counted.
    </ResponseField>

    <ResponseField name="name" type="String!" required>
      The merchant-facing name of the segment.
    </ResponseField>

    <ResponseField name="smsSubscriberCount" type="Int">
      Members subscribed to SMS marketing as of `countsRefreshedAt`.
    </ResponseField>

    <ResponseField name="type" type={<a href="/docs/api-reference/v3/reference/marketing/segment-type">SegmentType!</a>} required>
      How membership of this segment is determined.
    </ResponseField>

    <ResponseField name="updatedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
      When the segment was last updated.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="sentAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime</a>}>
  When the campaign finished sending. Null until it has finished.
</ResponseField>

<ResponseField name="smsVariants" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-sms-variant">[CampaignSmsVariant!]!</a>} required>
  The SMS content this campaign sends, oldest arm first. Empty for email campaigns.

  <Expandable title="fields" lazyRender>
    <ResponseField name="abTestWeight" type="Float!" required>
      The share of recipients this variant was sent to. A campaign with a single variant weights it 1.
    </ResponseField>

    <ResponseField name="position" type="Int!" required>
      This variant's position within the campaign, starting at 0.
    </ResponseField>

    <ResponseField name="template" type={<a href="/docs/api-reference/v3/reference/marketing/sms-template">SmsTemplate</a>}>
      The content this variant sent. Null when the template has since been deleted.

      **Requires:** [`marketing_templates_read`](/docs/api-reference/v3/reference/scopes#scope-marketing_templates_read)

      <Expandable title="fields" lazyRender>
        <ResponseField name="autoShortenLinks" type="Boolean!" required>
          Whether links in the body are shortened at send time.
        </ResponseField>

        <ResponseField name="content" type="String!" required>
          The SMS body **as authored**, before per-recipient substitution.
        </ResponseField>

        <ResponseField name="createdAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
          When the template was created.
        </ResponseField>

        <ResponseField name="id" type="ID!" required>
          The id of this template.
        </ResponseField>

        <ResponseField name="images" type={<a href="/docs/api-reference/v3/reference/marketing/sms-template-image">[SmsTemplateImage!]!</a>} required>
          Images sent with the message as MMS, in order. Dynamic product images and contact cards set in the editor are not listed.
        </ResponseField>

        <ResponseField name="legacyId" type="String!" required>
          The template's legacy Mongo ObjectId (24-char hex) from before the CockroachDB migration.
        </ResponseField>

        <ResponseField name="name" type="String!" required>
          The merchant-facing name of the template.
        </ResponseField>

        <ResponseField name="trigger" type={<a href="/docs/api-reference/v3/reference/marketing/marketing-trigger">MarketingTrigger!</a>} required>
          The trigger context this template is valid for. Immutable after create. UNKNOWN when the stored trigger is not modeled in this API version.
        </ResponseField>

        <ResponseField name="updatedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
          When the template was last edited.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="status" type={<a href="/docs/api-reference/v3/reference/marketing/campaign-status">CampaignStatus!</a>} required>
  Derived lifecycle status from schedule, send, failure, and cancellation timestamps.
</ResponseField>

<ResponseField name="tags" type="[String!]!" required>
  Tags the merchant applied to this campaign, in the order they applied them. Free-form and merchant-defined — Redo attaches no meaning to them, so they are the place a store's own categorisation (a promotion name, a season, a product line) is kept. Empty when the campaign is untagged.
</ResponseField>

<ResponseField name="updatedAt" type={<a href="/docs/api-reference/v3/reference/common/date-time">DateTime!</a>} required>
  When the campaign was last updated.
</ResponseField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.