Retrieve a campaign

GET/api/v1/campaigns/{campaign}
Requires anorganization API keywith the scopecampaigns:read

Parameters

NameInTypeDescription
campaignrequiredpathstringThe campaign identifier.

Request

GET/api/v1/campaigns/{campaign}
curl -X GET 'https://app.mailyte.com/api/v1/campaigns/01JBT8XQ2M9WYC3K4F6R7S8T9V' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY'
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

      The one lifecycle answer. `draft` is editable and going nowhere; `scheduled` is accepted and waiting for its send time; `sending` means the fan-out is running; `paused` means it stopped between chunks and is resumable; `sent` means the fan-out FINISHED, which is not the same as "everyone received it" — read `GET /campaigns/{campaign}/stats` for that, because a campaign can read `sent` with zero delivered; `canceled` means stopped for good, though it can still be resent. `unknown` means WE DID NOT RECOGNISE the stored status — it is not a reassurance and nothing is fine about it. It exists so a surprise is never published as a state implying a capability the campaign lacks: mapping it to `draft` would tell you the campaign is editable when it may be mid-send. Whether the campaign can actually go out is a separate question, answered only by `POST /campaigns/{campaign}/preflight` — in particular an organization awaiting marketing review is not a campaign state, because the campaign becomes sendable without being touched.

    • senderobject

      The identity this sends as. `null` means the relation was not loaded, not that there is no sender — `sender_id` is NOT NULL. The sender's verification state is deliberately not repeated here; whether an unverified sender blocks THIS campaign is preflight's `sender_unverified`.

      • idstring
      • namestring

        The sender's display name. In practice NEVER null: `senders.name` is NOT NULL, so a `sender` object that is present always carries one. The marker is defensive, not a case you have to handle — if the sender itself was not loaded the whole `sender` object is null, which is the field that says so.

      • emailstring
    • contentobject
      • subjectstring

        The subject line. `null` means NONE — none has been written — never "not included": unlike `html` and `text` this is a real answer in a list response too. A draft normally starts this way; a campaign with no subject AND no template cannot be sent, and preflight reports that as `no_content`.

      • template_idstring

        A campaign either carries its own body or renders a template. The send path prefers the template when both are set. `null` means NONE — this campaign renders its own `subject` / `html` / `text` and no template is attached — never "not included": it is a real answer in a list response too.

      • 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. `null` in a LIST response means NOT INCLUDED — we have not told you — and never "empty": a body has no size limit and a page of 25 campaigns would be megabytes nobody asked for. `has_html` is the field that says whether there is one. Fetch the campaign on its own to read it.

      • textstring

        The plain-text body — stored as `plain_text`, published as `text`, which is the spelling the send payload uses. `null` in a LIST response means NOT INCLUDED, not empty; `has_text` is the real boolean. 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 the list size, NOT a recipient total: lists and segments can overlap, exclusions are removed, and suppressed addresses are dropped at send. Null means the count was not read.

      • segmentsarray<object>

        Rule-based segments this campaign sends to. They carry no count: a segment has no fixed membership, its rules are evaluated against your contacts when the campaign sends, so any figure here would be a different number from the one that matters. Null only if the relation was not loaded.

        • idstring
        • namestring
      • 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

        Non-null ONLY when `state` is `scheduled`. The stored column outlives the intention — a cancel leaves the old time in place, and `POST /campaigns` accepts one on a draft without scheduling anything — so this is read from the state instead, and the two can no longer disagree.

      • 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 fan-out finished — stamped by the last chunk, at the same moment `state` becomes `sent`. `null` means NONE: it has not finished. That covers a draft, a scheduled campaign, one still sending or paused, AND a canceled one, because cancel stops the fan-out rather than completing it. A resend clears it back to null along with the rest of the campaign's send record. Finishing the fan-out is not the same as everybody receiving it — read `GET /campaigns/{campaign}/stats` for that.

    • resent_from_campaign_idstring

      The campaign this one was resent from — the only way to tell a resend from an original. It is a campaign id you can fetch. `null` means NONE: this campaign is an original, not carved out of another one. Never "we did not look" — it is a column on the row already read, present in a list response as well as a single campaign.

    • 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.