Developer Docs

The Meisa API

Meisa is behavioral lifecycle email for SaaS. Your app syncs each user's current state over a small REST API. Your growth team then owns every onboarding flow, lifecycle sequence, and triggered email from the dashboard. Most integrations use just two endpoints.

Integrate with an AI assistant

Paste this into Claude, Cursor, or ChatGPT and let it write your integration.

You are integrating my app with Meisa, a behavioral lifecycle email API for SaaS.
Read the full machine-readable spec first: https://meisa.io/llms-full.txt

Core model: my app syncs each user's CURRENT STATE to Meisa, and Meisa automations
(configured in the dashboard) react to changes. My code only needs two endpoints:
  1. POST /contacts/upsert/  — push user state (signup, login, plan change, churn)
  2. POST /emails/trigger/   — send transactional email (OTP, receipts, invites)

Base URL: https://api.meisa.io/api/v1
Auth: header "X-API-Key: meisa_live_..." on every request. JSON bodies.

Endpoints (path | scope | key fields):
- POST /contacts/upsert/        | contacts:write  | email (required), external_id, first_name, last_name, custom_fields (object, merged), tag_names (string[])
- POST /events/track/           | events:track    | event_name (required), email|external_id (one required), properties
- POST /contacts/{id}/add_tag/  | contacts:write  | tag_name OR tag_id
- POST /contacts/{id}/remove_tag/ | contacts:write | tag_name OR tag_id
- GET  /contacts/api/unsubscribed-emails/ | contacts:read | returns {as_of,count,emails[]} to suppress locally
- POST /sequences/enroll/       | sequences:enroll | email (required), sequence_slug (required, active)
- GET  /sequences/api/list/     | sequences:read  | lists active sequences + slugs
- POST /emails/trigger/         | emails:trigger  | trigger_key (required, configured in dashboard), to_email (required), variables, recipient, idempotency_key
- GET  /ping/                   | (any key)       | verify the key works

Map my needs like this:
- transactional/OTP/password-reset/receipt email -> POST /emails/trigger/ with a trigger_key
- start onboarding on signup -> upsert the user; a Meisa automation enrolls them
- tag/segment users by plan/churn/upgrade -> upsert the changed fields; automations tag them
- react to an in-product action -> POST /events/track/ with an event_name
- avoid emailing unsubscribed/bounced -> poll the unsubscribed-emails endpoint and suppress locally

Do NOT use these (they are not in the API): broadcasts/campaigns (dashboard only),
creating templates/triggers/sequences/automations (dashboard only), outbound webhooks.

Now: implement a small, reusable Meisa client for my stack, plus an upsert call on signup/login/
plan-change and an emails/trigger call for my transactional emails. Read my codebase, infer the
right fields for custom_fields from my user model, and add error handling (retry 5xx, not 4xx).
/llms.txt/llms-full.txt (full spec)Agents can fetch these URLs directly.

The core idea

You don't script email logic in your codebase. You sync state, and Meisa reacts. When you upsert a contact and a field changes (say plan goes from free to pro), the automations your team configured in Meisa run automatically: tags get added, sequences get enrolled, emails go out. Your code stays tiny and stable.

The two endpoints you'll actually use

POST /contacts/upsert/ to push user state, and POST /emails/trigger/ to send transactional email. Everything else is optional.

A complete integration, in two calls

Sync a user when they sign up or their state changes:

sync a user
curl -X POST "https://api.meisa.io/api/v1/contacts/upsert/" \
  -H "X-API-Key: meisa_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "external_id": "usr_12345",
    "first_name": "Sarah",
    "custom_fields": { "plan": "pro", "signin_count": 27 }
  }'

Send a transactional email by referencing a trigger you configured in the dashboard:

send transactional email
curl -X POST "https://api.meisa.io/api/v1/emails/trigger/" \
  -H "X-API-Key: meisa_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger_key": "verification_code",
    "to_email": "[email protected]",
    "variables": { "name": "Sarah", "code": "294817" }
  }'

Explore

Not part of the API

Broadcasts (one-time campaigns) are managed by humans in the Meisa dashboard, or driven by AI through the Meisa MCP server. There is no broadcasts endpoint for API keys, and outbound webhooks are not currently offered. Stick to the endpoints documented here.