Theme

Event contract

Events are the trigger stream — the one way the outside world tells Mimeo that something happened. Everything the automation engine does starts here.

An event is a name, a person, and whatever details you want to carry. There is no schema and there never will be: your app's vocabulary is your data, not our product vocabulary.

POST /api/v1/events
Authorization: Bearer mm_your_token
Content-Type: application/json

{
  "email": "[email protected]",
  "name": "signed_up",
  "details": { "plan": "trial", "source": "ads" },
  "occurred_at": "2026-07-29T10:00:00Z"
}

The fields

FieldNotes
emailRequired. The universal key — lowercased, and the person is created if they're new.
nameRequired. Your own vocabulary. Triggers match on it exactly.
detailsAny flat object. Trigger matches and event_occurred conditions read these.
occurred_atOptional. Defaults to now. Timeline ordering.
dedup_keyOptional. A repeat of the same key is recognised as a duplicate and does nothing, which makes an at-least-once sender safe.
personOptional. first_name, last_name, fields, tags — upserted alongside the event.
attributionOptional, first touch only: landing page, referrer, UTMs, device, country.

Batching

Send up to 100 at once as { "events": [ … ] }. The response carries a per-event result, so a partial failure tells you exactly which ones.

{ "results": [
    { "status": "created",   "person_id": 41, "event_id": 902 },
    { "status": "duplicate", "person_id": 41, "event_id": 887 },
    { "status": "error",     "error": "email is required" } ] }

Events Mimeo writes itself

Your events aren't the only ones in the stream. State changes fire events too, so a flow can trigger on them exactly as it would on yours:

EventWhen
tag_added · tag_removedA tag changes, by hand or by a flow. Details carry the tag.
field_changedA custom field changes. Details carry the key, the old value and the new one.
unsubscribed · resubscribedSuppression state changes. Details carry the reason and how it happened.
sequence_completedSomeone reaches the end of a sequence.

A flow's fire_event step writes one too — which is how one flow hands off to another. The validator warns (self_trigger) if a flow fires the event that triggers itself.

Money is events

Purchases, subscriptions and payments are recorded from events with the right names and details — Mimeo never integrates a payment processor directly, because your systems already know and one source of truth beats two. See People for the shapes.

What events are not

Opens and clicks are not events. They're telemetry, in their own tables, with bot filtering — deliberately not part of the trigger stream, because a flow branching on "opened" is a flow branching on a number that Apple Mail Privacy Protection inflates. Use the opened_email and clicked_email conditions if you want them, knowing that.

Tags don't decide. Tags describe. Anything a flow branches on should be real state — a field, a purchase, a subscription, an event that actually happened.

Designing your event names

See also: Events API · Flow schema