# Meisa > Meisa is behavioral lifecycle email for SaaS. Your app syncs user state to Meisa over a small REST API; your growth team then owns every onboarding flow, lifecycle sequence, and triggered email from the Meisa dashboard. The integration philosophy: your code only syncs current user state and fires transactional emails. Tagging, sequence enrollment, and event reactions are configured once in Meisa as automations and run automatically when the data you sync changes. Base URL: `https://api.meisa.io/api/v1` Auth: send your API key in the `X-API-Key` header on every request. Keys look like `meisa_live_...` and are created in Settings → API Keys. Each key has scopes. Verify a key: `GET https://api.meisa.io/api/v1/ping/` ## The two endpoints most integrations need - Sync a user: `POST /contacts/upsert/` (scope `contacts:write`). Send the user's current state keyed by `email` (and ideally `external_id`). Custom data goes in `custom_fields`. Meisa automations react to changes. - Send a transactional email: `POST /emails/trigger/` (scope `emails:trigger`). Identify a dashboard-configured trigger by `trigger_key`, send to `to_email`, pass `variables`. ## Full endpoint list - `POST /contacts/upsert/` — create/update a contact by email or external_id (scope: contacts:write) - `POST /events/track/` — record a custom event for a contact; fires automations (scope: events:track) - `POST /contacts/{id}/add_tag/` — add a tag to a contact (scope: contacts:write) - `POST /contacts/{id}/remove_tag/` — remove a tag from a contact (scope: contacts:write) - `GET /contacts/api/unsubscribed-emails/` — list emails that must not be sent to (scope: contacts:read) - `POST /sequences/enroll/` — enroll a contact in a sequence by slug (scope: sequences:enroll) - `POST /sequences/api/bulk-enroll/` — enroll up to 500 emails in a sequence (scope: sequences:enroll) - `GET /sequences/api/list/` — list active sequences and their slugs (scope: sequences:read) - `GET /sequences/api/contact-enrollments/` — list a contact's enrollments (scope: sequences:read) - `POST /emails/trigger/` — send a triggered/transactional email (scope: emails:trigger) - `GET /ping/` — verify an API key (any valid key) ## Docs - [API overview & AI prompt](https://meisa.io/docs): start here. - [Quickstart](https://meisa.io/docs/quickstart): first sync + first triggered email. - [Authentication & scopes](https://meisa.io/docs/authentication) - [Contacts & upsert](https://meisa.io/docs/contacts): the core endpoint and custom_fields. - [Events](https://meisa.io/docs/events) - [Tags](https://meisa.io/docs/tags) - [Sequences](https://meisa.io/docs/sequences) - [Triggered emails](https://meisa.io/docs/triggered-emails) - [Automations: you sync, Meisa reacts](https://meisa.io/docs/automations) - [Full reference](https://meisa.io/docs/reference) - [Full machine-readable spec](https://meisa.io/llms-full.txt): the complete API in one file, ideal to paste into an AI coding assistant. ## Notes - Broadcasts (one-time campaigns) are NOT part of this REST API. They are managed by humans in the Meisa dashboard, or driven by AI through the Meisa MCP server. Do not attempt to send broadcasts via X-API-Key. - This API is for syncing state and firing transactional/triggered email. You generally do not call tag or sequence endpoints directly from your app; instead you sync state and let Meisa automations add tags and enroll sequences for you.