MARKETING AUTOMATION

Built from the ground up to be open — and ready for AI.

Every brief, every dispatch, every result in Gagewire is a structured block behind a REST API — not a locked-in form. That is a design choice, not an add-on. An AI assistant can draft the work, a script can file it, a tool can send it, and the numbers come back through the same door. The whole loop — plan, dispatch, execute, measure, learn — was drawn for automation before the first line was written.

PlanDispatchExecuteMeasureLearn
Two collaborators running an end-to-end marketing loop
WHO DOES WHAT

Four systems, one source of truth.

Marketing automation is not one product that does everything. It is a chain of systems that each own one job — drafting, filing, sending, measuring — and one place they all agree on. Gagewire is that place. Everything else reads from it and writes to it.

GAGEWIREus

The source of truth

Holds the brief, the canonical dispatch blocks, the send schedule, and the results — all behind one REST API. Nothing else stores the work; everything else talks to it.

AI ASSISTANT

Drafts the work

Connected through MCP, the assistant drafts a brief and returns dispatches as the same canonical blocks the editor would produce. It writes; it does not send.

YOUR SCRIPTS & TOOLS

Move the work

File a brief, flip a dispatch from draft to ready to sent, ingest results — all ordinary REST calls with a Gagewire API key. The status transitions are the automation.

YOUR CHANNEL TOOLS

Carry the send

The email provider, the social scheduler — the systems that actually push send. They read a ready dispatch from Gagewire and write the outcome back as a result.

What gets automated is the drafting (the assistant), the status transitions and result ingestion (your scripts), and the send itself (your channel tools). What Gagewire automates is the structure: every dispatch is already a block, every result is already a value, so nothing has to be parsed or re-typed to move between these roles.

A WORKED EXAMPLE

One assignment, two dispatches, end to end.

A product launch, briefed in plain language. An AI assistant drafts the brief and two linked dispatches — a personal email and a LinkedIn post. The REST API files them, marks them ready, and later reads the results back. One coherent loop, not a pile of disconnected steps.

AAn AI assistant drafts the work

Pointed at the workspace through MCP, the assistant drafts a brief and returns the two dispatches as canonical blocks — the same shape the editor would produce.

# The assistant is given a one-line intent and returns structured blocks
draft = assistant.draft_assignment(
  intent="Launch our new booking tool; reach existing customers and our LinkedIn audience",
  channels=["Personal email", "LinkedIn post"],
)

# draft.brief  -> { objective, audience, message, ... }
# draft.dispatches -> [
#   { type: "Personal email",  blocks: [ ... ] },
#   { type: "LinkedIn post",   blocks: [ ... ] },
# ]
BFile the brief as a campaign
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    op: "create",
    entity: "Campaign",
    data: {
      brand_id: BRAND_ID,
      name: "Booking tool launch",
      objective: "Get existing customers onto the new booking tool",
      audience: "Current customers and our LinkedIn followers",
      central_message: "Booking just got one tap simpler",
      channels: ["Direct outreach (1:1 email, call, DM)", "Social posts (organic)"],
      metrics: [
        { key: "opens", label: "Email opens", type: "count" },
        { key: "clicks", label: "Clicks", type: "count" },
        { key: "signups", label: "New signups", type: "count" },
      ],
    },
  }),
});
CFile the two linked dispatches

Each dispatch stores its content as ordered blocks. The plain-text content field is derived by the server on every write; the type must be a known dispatch type.

// 1. The personal email
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "create",
    entity: "Dispatch",
    data: {
      campaign_id: CAMPAIGN_ID,
      brand_id: BRAND_ID,
      type: "Personal email",            // known dispatch type
      title: "Launch note to customers",
      blocks: [
        { type: "subject", content: "Booking just got one tap simpler" },
        { type: "body",   content: "<p>We just launched a faster way to book...</p>" },
        { type: "cta",    content: "Try it now", config: { url: "https://..." } },
        { type: "signoff", content: "Thanks, the team" },
      ],
    },
  }),
});

// 2. The LinkedIn post
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "create",
    entity: "Dispatch",
    data: {
      campaign_id: CAMPAIGN_ID,
      brand_id: BRAND_ID,
      type: "LinkedIn post",
      title: "Launch day on LinkedIn",
      blocks: [
        { type: "headline", content: "We just made booking one tap simpler" },
        { type: "body",     content: "<p>Today we are launching...</p>" },
        { type: "cta",      content: "See it live", config: { url: "https://..." } },
        { type: "hashtags", content: "#productlaunch #booking" },
      ],
    },
  }),
});
DMark ready, then sent

A dispatch moves through draft → ready → sent. You mark it ready inside Gagewire; the actual send is wired by you today — through the API, an MCP-connected assistant, or your channel tool.

// Mark the email ready to send
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "update",
    entity: "Dispatch",
    id: EMAIL_DISPATCH_ID,
    data: { status: "ready", send_date: "2026-09-22" },
  }),
});

// After you send it through your email tool, mark it sent
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "update",
    entity: "Dispatch",
    id: EMAIL_DISPATCH_ID,
    data: { status: "sent" },
  }),
});
ERecord and read the results

The results come back as structured values, joined to the channels that produced them. The loop closes — and the next assignment starts from what you learned.

// Record the email result
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "create",
    entity: "Result",
    data: {
      campaign_id: CAMPAIGN_ID,
      brand_id: BRAND_ID,
      channel: "Direct outreach (1:1 email, call, DM)",
      values: [
        { key: "opens",   value: 1840 },
        { key: "clicks",  value: 412 },
        { key: "signups", value: 96 },
      ],
      attribution: "direct",
      what_worked: "The one-tap framing in the subject line",
      change_next: "Lead with the benefit, not the feature name",
    },
  }),
});

// Read all results for the campaign back
await fetch("https://gagewire.com/functions/gagewireApi", {
  method: "POST",
  headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    op: "filter",
    entity: "Result",
    query: { campaign_id: CAMPAIGN_ID },
    sort: "-created_date",
  }),
});
WHO CARRIES THE SEND

Vendors carry it. Gagewire pays and tracks it.

The send is not a gap you wire yourself — it is work done by people you pay to execute: a freelancer who runs the email list, an agency that places the social, a tool that fires the SMS. Gagewire holds the brief, the dispatch, and the schedule, routes the payment to whoever carries the send, and records the result they bring back. The loop is already closed: plan, dispatch, pay to execute, measure, learn. Native delivery connectors arrive later, and because every dispatch is already a structured block, they arrive without a redesign.

This same loop is where your downstream experimentation plugs in. A channel's hypothesis is a falsifiable claim; the verdict you record closes it inside Gagewire, while the actual test — A/B, multivariate, the optimization an ML pipeline runs — is executed by the channel tool or your own pipeline. As those systems test a dispatch and learn from it, what comes back (variants, segments, lift, confidence) can attach to the same dispatch record as additional fields, so a dispatch grows from a draft into a tested, measured unit without losing its place in the assignment.

Start the loop with one assignment.