Update a campaign

PATCH/api/v1/campaigns/{campaign}
Requires anorganization API keywith the scopecampaigns:write

Parameters

NameInTypeDescription
campaignrequiredpathstringThe campaign identifier.

Request body

  • namestring

    A name for your team, like October newsletter. Recipients never see it.

  • sender_idstring

    The ID of a verified sender, which sets the From name and address. Copy it from Sending → Senders in the dashboard, or read it from GET /senders.

  • subjectstring

    The subject line. It can use {{ tags }} like {{name}}. Needed before the campaign can be sent.

  • htmlstring

    The email's HTML. Leave it out when you use template_id, or for a plain email (send plain_text alone).

  • plain_textstring

    A plain email: send this alone, with no html or template_id, and we lay it out simply and add the unsubscribe line. Sent with html, it is that email's text version.

  • template_idstring

    Optional. Use one of your templates for the content instead of html. Copy its ID from Templates in the dashboard, or read it from GET /email-templates.

  • scheduled_atstring

    Optional. When you want it to go out, in ISO 8601 with a time zone. Saving it does not schedule anything: the campaign goes out only when you call POST /campaigns/{id}/schedule (pass the time there) or POST /campaigns/{id}/send.

  • list_idsarray<string>

    The lists to send to. Copy IDs from Contacts → Lists in the dashboard, or read them from GET /contact-lists.

  • segment_idsarray<string>

    The segments to send to. Copy IDs from Contacts → Segments in the dashboard, or read them from GET /segments.

  • include_unlistedboolean

    Also send to contacts who are on no list at all. Defaults to false.

  • excluded_contact_idsarray<string>

    Contacts to leave out even though they are on the chosen lists or segments, by contact ID.

Request

PATCH/api/v1/campaigns/{campaign}
curl -X PATCH 'https://app.mailyte.com/api/v1/campaigns/01JBT8XQ2M9WYC3K4F6R7S8T9V' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "October newsletter",
    "subject": "Our October update",
    "html": "<p>Hi {{name}},</p><p>Here is what is new this month.</p>",
    "list_ids": [
      "01JBT8XQ2M9WYC3K4F6R7S8T9V"
    ]
  }'
The key names its own organization, so no X-Organization-ID header is needed.

Response

Success.

  • dataobject

    The field SET never varies between a list and a single campaign. Two values do: content.html / content.text and audience.excluded_contact_ids are null in a list response. See those fields.

    • objectstringcampaign
    • idstring

      Unique identifier for the campaign.

    • namestring
    • statestringdraft | scheduled | sending | paused | sent | canceled | unknown

      Where the campaign is. - draft: editable, not going anywhere. - scheduled: waiting for its send time. - sending: going out now. - paused: stopped partway and can be resumed. - sent: finished sending. Read GET /campaigns/{campaign}/stats for how many were delivered. - canceled: stopped for good, though it can be resent. - unknown: a state we did not recognise. Contact support. To see whether a campaign can go out, use POST /campaigns/{campaign}/preflight.

    • senderobject

      The sender this campaign sends as. Whether the sender is verified is checked by preflight.

      • idstring
      • namestring

        The sender's display name.

      • emailstring
    • contentobject
      • subjectstring

        The subject line. Null when none has been written. A campaign with no subject and no template cannot be sent.

      • template_idstring

        The template this campaign uses, if any. When a template is set, it is used instead of the campaign's own subject, html and text. Null when the campaign uses its own content.

      • has_htmlboolean

        ALWAYS a real answer, in a list as well as on a single campaign. This is the boolean to test — not html !== null.

      • has_textboolean

        ALWAYS a real answer, in a list as well as on a single campaign. This is the boolean to test — not text !== null.

      • htmlstring

        The HTML body. Left out (null) in lists to keep them small: has_html says whether there is one. Fetch the campaign on its own to read it.

      • textstring

        The plain-text body. Left out (null) in lists to keep them small: has_text says whether there is one. Fetch the campaign on its own to read it.

    • audienceobject

      Static lists plus rule-based segments, minus per-campaign exclusions — the union-then-subtract the send path materialises.

      • listsarray<object>

        The static lists this campaign sends to, named so you do not have to fetch each one to display it. Null only if the relation was not loaded.

        • idstring
        • namestring
        • contact_countinteger

          How many contacts are on the list. This is not the number of recipients: lists and segments can overlap, and exclusions and suppressed addresses are removed when sending.

      • segmentsarray<object>

        The segments this campaign sends to. A segment's members are worked out when the campaign sends, so no count is given.

        • idstring
        • namestring
      • includes_unlistedboolean

        Whether the campaign also goes to contacts who are on no list. A campaign can target only these.

      • excludedobject

        Contacts held back from this campaign only; their list membership is untouched.

        • countinteger

          How many contacts are excluded. Always present, including in a list response, so you can tell "none excluded" from "not told you" without fetching the campaign.

        • contact_idsarray<string>

          null in a LIST response means NOT INCLUDED, never "there are none" — the set is unbounded, which is why count sits beside it. Fetch the campaign on its own to read the ids.

    • scheduleobject
      • scheduled_forstring

        When the campaign will go out. Set only while state is scheduled.

      • started_atstring

        When the fan-out began. Null until it does — and that is exactly the cut that makes every count in /stats and the whole timeline in /report null rather than zero.

      • completed_atstring

        When the campaign finished sending. Null until then, and for a canceled campaign. Finished sending is not the same as delivered; read GET /campaigns/{campaign}/stats for that.

    • resent_from_campaign_idstring

      The campaign this one was resent from. Null when it is an original.

    • created_atstring
    • updated_atstring

Returned inside the standard envelope.

Errors

StatusWhen
401The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist.
403The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys.
404No such resource in this organization.
422The request was understood but the values were not acceptable.
429Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait.

Every status, with what causes it and what to do, is on the error reference.