Mailpark
API reference

Sequences

Automated emails that follow an event: a contact enters when trigger_event is recorded, runs through the steps, and leaves early on any exit_events. Steps send emails, wait, wait for an event, or branch on a check.

Sequences start as draft. Simulate one first: it fast-forwards a test contact through every step into the test inbox. Turning a sequence on with an API key needs the sequences:activate scope, which only test keys can have.

The Sequence object
type Sequence = {
  id: string; name: string;
  trigger_event: string;
  steps: Step[];
  exit_events: string[]; reentry_days: number;
  topic: string;
  status: "draft" | "on" | "off";
  stats: { active: number; completed: number; exited: number };
  created_at: string; updated_at: string;
};

type Step =
  | { type: "email"; template_key: string }
  | { type: "wait"; duration: string }               // ISO-8601: PT1H, P2D, P1W
  | { type: "wait_for_event"; event: string; timeout: string; on_timeout: "continue" | "exit" }
  | { type: "check"; condition: Condition; yes: Step[]; no: Step[] } // branches rejoin after
  | { type: "exit" };

type Condition =
  | { kind: "event"; event: string; since: "entered" | "ever" }
  | { kind: "field"; field: string; op: "equals" | "not_equals" | "contains" | "exists" | "not_exists" | "gt" | "lt"; value?: unknown }
  | { kind: "email"; activity: "opened" | "clicked" }; // the previous email this sequence sent

Create a sequence

POST/v1/sequences

A new sequence in draft. At least one email step, at most 50 steps counting branches, checks nested at most 5 deep.

scope sequences:write

Body

  • namestringrequired

    Shown in the web app.

  • trigger_eventstringrequired

    The event that enrols a contact.

  • stepsStep[]required

    See the Step type above. Step ids are optional (step_<n> by default).

  • exit_eventsstring[]

    Events that take a contact out early, e.g. upgraded.

  • reentry_daysinteger

    Days before the same contact can enter again.

  • topicstring

    The marketing topic people can unsubscribe from.

curl -X POST https://api.mailpark.io/v1/sequences \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Onboarding",
    "trigger_event": "signed_up",
    "steps": [
      {
        "type": "email",
        "template_key": "welcome"
      },
      {
        "type": "wait_for_event",
        "event": "project_created",
        "timeout": "P1D",
        "on_timeout": "continue"
      },
      {
        "type": "check",
        "condition": {
          "kind": "event",
          "event": "project_created",
          "since": "entered"
        },
        "yes": [
          {
            "type": "email",
            "template_key": "onboarding-tip-2"
          }
        ],
        "no": [
          {
            "type": "email",
            "template_key": "onboarding-tip-1"
          },
          {
            "type": "wait",
            "duration": "P2D"
          },
          {
            "type": "email",
            "template_key": "onboarding-tip-2"
          }
        ]
      }
    ],
    "exit_events": [
      "upgraded"
    ],
    "reentry_days": 90,
    "topic": "onboarding"
  }'
Response · 200
{
  "id": "seq_onboard",
  "name": "Onboarding",
  "trigger_event": "signed_up",
  "steps": [
    {
      "type": "email",
      "template_key": "welcome"
    },
    {
      "type": "wait_for_event",
      "event": "project_created",
      "timeout": "P1D",
      "on_timeout": "continue"
    },
    {
      "type": "check",
      "condition": {
        "kind": "event",
        "event": "project_created",
        "since": "entered"
      },
      "yes": [
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ],
      "no": [
        {
          "type": "email",
          "template_key": "onboarding-tip-1"
        },
        {
          "type": "wait",
          "duration": "P2D"
        },
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ]
    }
  ],
  "exit_events": [
    "upgraded"
  ],
  "reentry_days": 90,
  "topic": "onboarding",
  "status": "draft",
  "stats": {
    "active": 0,
    "completed": 0,
    "exited": 0
  },
  "created_at": "2026-10-22T10:02:11Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

List sequences

GET/v1/sequences

All sequences with their stats.

curl https://api.mailpark.io/v1/sequences \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "seq_onboard",
      "name": "Onboarding",
      "trigger_event": "signed_up",
      "steps": [
        {
          "type": "email",
          "template_key": "welcome"
        },
        {
          "type": "wait_for_event",
          "event": "project_created",
          "timeout": "P1D",
          "on_timeout": "continue"
        },
        {
          "type": "check",
          "condition": {
            "kind": "event",
            "event": "project_created",
            "since": "entered"
          },
          "yes": [
            {
              "type": "email",
              "template_key": "onboarding-tip-2"
            }
          ],
          "no": [
            {
              "type": "email",
              "template_key": "onboarding-tip-1"
            },
            {
              "type": "wait",
              "duration": "P2D"
            },
            {
              "type": "email",
              "template_key": "onboarding-tip-2"
            }
          ]
        }
      ],
      "exit_events": [
        "upgraded"
      ],
      "reentry_days": 90,
      "topic": "onboarding",
      "status": "on",
      "stats": {
        "active": 132,
        "completed": 840,
        "exited": 61
      },
      "created_at": "2026-10-22T10:02:11Z",
      "updated_at": "2026-10-22T10:02:11Z"
    }
  ],
  "next_cursor": null
}
▶ Try it in the playground

Get a sequence

GET/v1/sequences/{id}

One sequence with its steps and stats.

Path parameters

  • idstringrequired

    seq_…

curl https://api.mailpark.io/v1/sequences/seq_onboard \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "id": "seq_onboard",
  "name": "Onboarding",
  "trigger_event": "signed_up",
  "steps": [
    {
      "type": "email",
      "template_key": "welcome"
    },
    {
      "type": "wait_for_event",
      "event": "project_created",
      "timeout": "P1D",
      "on_timeout": "continue"
    },
    {
      "type": "check",
      "condition": {
        "kind": "event",
        "event": "project_created",
        "since": "entered"
      },
      "yes": [
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ],
      "no": [
        {
          "type": "email",
          "template_key": "onboarding-tip-1"
        },
        {
          "type": "wait",
          "duration": "P2D"
        },
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ]
    }
  ],
  "exit_events": [
    "upgraded"
  ],
  "reentry_days": 90,
  "topic": "onboarding",
  "status": "draft",
  "stats": {
    "active": 0,
    "completed": 0,
    "exited": 0
  },
  "created_at": "2026-10-22T10:02:11Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

Update a sequence

PATCH/v1/sequences/{id}

Changes the name, steps, trigger or exits. Contacts already in it carry on from the step they're at.

scope sequences:write

Path parameters

  • idstringrequired

    seq_…

Body

  • namestring

    Name.

  • trigger_eventstring

    Trigger.

  • stepsStep[]

    The whole list of steps.

  • exit_eventsstring[]

    Exit events.

  • reentry_daysinteger

    Re-entry window.

curl -X PATCH https://api.mailpark.io/v1/sequences/seq_onboard \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "exit_events": [
      "upgraded",
      "deleted_account"
    ]
  }'
Response · 200
{
  "id": "seq_onboard",
  "name": "Onboarding",
  "trigger_event": "signed_up",
  "steps": [
    {
      "type": "email",
      "template_key": "welcome"
    },
    {
      "type": "wait_for_event",
      "event": "project_created",
      "timeout": "P1D",
      "on_timeout": "continue"
    },
    {
      "type": "check",
      "condition": {
        "kind": "event",
        "event": "project_created",
        "since": "entered"
      },
      "yes": [
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ],
      "no": [
        {
          "type": "email",
          "template_key": "onboarding-tip-1"
        },
        {
          "type": "wait",
          "duration": "P2D"
        },
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ]
    }
  ],
  "exit_events": [
    "upgraded",
    "deleted_account"
  ],
  "reentry_days": 90,
  "topic": "onboarding",
  "status": "draft",
  "stats": {
    "active": 0,
    "completed": 0,
    "exited": 0
  },
  "created_at": "2026-10-22T10:02:11Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

Simulate a sequence

POST/v1/sequences/{id}/simulate

Fast-forwards a test contact through the whole sequence and returns the timeline. Every email lands in the test inbox. Add what-ifs to pick the path through waits and checks.

Path parameters

  • idstringrequired

    seq_…

Body

  • emailstring

    Test contact. Default simulated+<sequence-name>@example.com.

  • eventsobject[]

    Events the contact does: [{ name, after? }], after as an ISO-8601 duration.

  • opensboolean

    Pretend the contact opens every email.

  • clicksboolean

    Pretend the contact clicks every email.

curl -X POST https://api.mailpark.io/v1/sequences/seq_onboard/simulate \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "test@example.com",
    "events": [
      {
        "name": "project_created",
        "after": "PT6H"
      }
    ]
  }'
Response · 200
{
  "sequence_id": "seq_onboard",
  "contact_email": "test@example.com",
  "timeline": [
    {
      "offset": "PT0S",
      "at": "2026-10-22T10:02:11Z",
      "step": null,
      "action": "enrolled",
      "template_key": null,
      "message_id": null,
      "detail": "signed_up was recorded"
    },
    {
      "offset": "PT0S",
      "at": "2026-10-22T10:02:11Z",
      "step": 1,
      "action": "sent",
      "template_key": "welcome",
      "message_id": "msg_01JB4QS1",
      "detail": "Sent welcome"
    },
    {
      "offset": "PT6H",
      "at": "2026-10-22T16:02:11Z",
      "step": 2,
      "action": "waited",
      "template_key": null,
      "message_id": null,
      "detail": "project_created arrived after 6 hours"
    },
    {
      "offset": "PT6H",
      "at": "2026-10-22T16:02:11Z",
      "step": 3,
      "action": "sent",
      "template_key": "onboarding-tip-2",
      "message_id": "msg_01JB4QS2",
      "detail": "Check was yes: sent onboarding-tip-2"
    },
    {
      "offset": "PT6H",
      "at": "2026-10-22T16:02:11Z",
      "step": null,
      "action": "completed",
      "template_key": null,
      "message_id": null,
      "detail": "Reached the end"
    }
  ],
  "next_steps": [
    "Read the emails with GET /v1/test-inbox.",
    "Turn it on with POST /v1/sequences/seq_onboard/on."
  ]
}
▶ Try it in the playground

Turn a sequence on

POST/v1/sequences/{id}/on

Starts enrolling contacts. With an API key this needs sequences:activate, which only test keys can have; on a live account a person turns it on in the web app.

scope sequences:activateAPI keys: test keys only

Path parameters

  • idstringrequired

    seq_…

curl -X POST https://api.mailpark.io/v1/sequences/seq_onboard/on \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 200
{
  "id": "seq_onboard",
  "name": "Onboarding",
  "trigger_event": "signed_up",
  "steps": [
    {
      "type": "email",
      "template_key": "welcome"
    },
    {
      "type": "wait_for_event",
      "event": "project_created",
      "timeout": "P1D",
      "on_timeout": "continue"
    },
    {
      "type": "check",
      "condition": {
        "kind": "event",
        "event": "project_created",
        "since": "entered"
      },
      "yes": [
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ],
      "no": [
        {
          "type": "email",
          "template_key": "onboarding-tip-1"
        },
        {
          "type": "wait",
          "duration": "P2D"
        },
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ]
    }
  ],
  "exit_events": [
    "upgraded"
  ],
  "reentry_days": 90,
  "topic": "onboarding",
  "status": "on",
  "stats": {
    "active": 0,
    "completed": 0,
    "exited": 0
  },
  "created_at": "2026-10-22T10:02:11Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

Turn a sequence off

POST/v1/sequences/{id}/off

Stops new enrolments and pauses contacts already in it.

scope sequences:write

Path parameters

  • idstringrequired

    seq_…

curl -X POST https://api.mailpark.io/v1/sequences/seq_onboard/off \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 200
{
  "id": "seq_onboard",
  "name": "Onboarding",
  "trigger_event": "signed_up",
  "steps": [
    {
      "type": "email",
      "template_key": "welcome"
    },
    {
      "type": "wait_for_event",
      "event": "project_created",
      "timeout": "P1D",
      "on_timeout": "continue"
    },
    {
      "type": "check",
      "condition": {
        "kind": "event",
        "event": "project_created",
        "since": "entered"
      },
      "yes": [
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ],
      "no": [
        {
          "type": "email",
          "template_key": "onboarding-tip-1"
        },
        {
          "type": "wait",
          "duration": "P2D"
        },
        {
          "type": "email",
          "template_key": "onboarding-tip-2"
        }
      ]
    }
  ],
  "exit_events": [
    "upgraded"
  ],
  "reentry_days": 90,
  "topic": "onboarding",
  "status": "off",
  "stats": {
    "active": 0,
    "completed": 0,
    "exited": 0
  },
  "created_at": "2026-10-22T10:02:11Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

List enrollments

GET/v1/sequences/{id}/enrollments

Who is in the sequence, the step they're at and what they're waiting for.

Path parameters

  • idstringrequired

    seq_…

Query parameters

  • limitinteger

    How many to return, 1–100. Default 50.

  • cursorstring

    The next_cursor from the previous page.

curl https://api.mailpark.io/v1/sequences/seq_onboard/enrollments \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "enr_2Lp0",
      "sequence_id": "seq_onboard",
      "contact_id": "con_7Yt1",
      "email": "jane@example.com",
      "current_step": 1,
      "current_step_id": "step_2",
      "waiting_for": "project_created",
      "status": "active",
      "exit_reason": null,
      "next_step_at": "2026-10-23T10:02:11Z",
      "created_at": "2026-10-22T10:02:11Z"
    }
  ],
  "next_cursor": null
}
▶ Try it in the playground

Count people per step

GET/v1/sequences/{id}/step-counts

How many contacts are at each step right now.

Path parameters

  • idstringrequired

    seq_…

curl https://api.mailpark.io/v1/sequences/seq_onboard/step-counts \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "data": [
    {
      "step_id": "step_2",
      "active": 88,
      "paused": 0
    },
    {
      "step_id": "step_3_no_2",
      "active": 44,
      "paused": 0
    }
  ]
}
▶ Try it in the playground