# Docs Mara is hired, not installed, so there is not much to integrate. What she needs from your side is data: who your users are and what they do. Two surfaces carry it, and both are documented here in enough detail that an AI coding agent can do the work for you. ## Connect your data **[Mara API](/docs/api).** One endpoint, two operations. `identify` upserts a contact, `track` records what happened and fires matching programs. Bearer-key auth, batching, idempotency, rate limits, naming guidance, runnable examples. **[Webhooks](/docs/webhooks).** Stripe, Polar, and Clerk. Paste Mara's per-tenant URL into the provider and the provider's signing secret into Mara. Events arrive signature-verified and normalized into the eight lifecycle moments programs trigger on. Contacts can also arrive by CSV or JSON import from the settings page; no docs needed, the upload form explains itself. ## Connect your AI tools **[MCP server](/docs/mcp).** Point Claude Code, Claude Desktop, Cursor, or any other MCP client at your workspace. Read programs, drafts, and the Playbook, and act on your behalf (draft, approve, pause), under the same guardrails as your dashboard chat. ## Coming from another tool **[Glossary](/docs/glossary).** Every term mapped from what Loops, Customer.io, Klaviyo, Encharge and Sequenzy call it. A flow, a loop, a sequence and a campaign are all a **program** here. An audience is a **segment**. Also the parts with no equivalent anywhere, starting with the approval queue: Mara drafts and then stops, so if it looks like nothing is sending, your programs are running and waiting on you. ## For AI coding agents Every docs page has a raw markdown twin: append `.md` to the URL. There is also [llms.txt](https://hiremara.com/llms.txt) at the site root, and [llms-full.txt](https://hiremara.com/llms-full.txt) with the full docs inlined. Your founder's dashboard (Settings, Integrations, Mara API) has a ready-made prompt that includes the tenant's real endpoint URL. ## Where things are decided Integration gets data in. Everything else, drafting programs, approving emails, pausing sends, teaching Mara what to say, happens in your dashboard and chat. If you are evaluating Mara rather than wiring her up, start at [how it works](/how-it-works). --- # Mara API Send your product's events to Mara. One endpoint, two operations: `identify` tells Mara who a contact is, `track` tells her what happened. Any active program whose trigger matches an incoming event fires automatically, per contact. This page is the complete spec, written for humans and for AI coding agents. The raw markdown lives at [hiremara.com/docs/api.md](https://hiremara.com/docs/api.md). The fastest path: open Settings, then Integrations, then Mara API in your dashboard and copy the ready-made prompt into Claude Code, Cursor, or whatever agent writes your code. It links back here. If your agent already speaks MCP, the fastest setup of all skips Settings entirely: `setup_events_ingestion` mints the key and hands back your exact endpoint, and `check_recent_events` confirms your test event landed. See [/docs/mcp](/docs/mcp). If your "events" are billing events from Stripe or Polar, do not send them through this API. Point your provider's webhooks at Mara instead, so payloads arrive signature-verified and normalized. See [Webhooks](/docs/webhooks). ## Endpoint ``` POST https://hiremara.com/api/tenants/{tenantId}/events Content-Type: application/json Authorization: Bearer {your ingestion key} ``` Your exact endpoint URL, with your tenant id filled in, is shown in Settings under Integrations, Mara API. ## Authentication Auth is a per-tenant bearer key with the prefix `mara_ing_`. Generate it on the same settings row. The raw key is shown exactly once at generation; Mara stores only a hash. Generating a new key immediately revokes the old one. This is a server-to-server key. Keep it in an environment variable on your backend. Never ship it to a browser or a mobile client. ## Request body The body is a single operation, or a batch of up to 100: ```json { "batch": [ { "type": "identify", "userId": "u_42", "email": "ada@example.com", "name": "Ada", "traits": { "plan": "starter" } }, { "type": "track", "event": "user.signed_up", "userId": "u_42", "messageId": "evt_001" } ] } ``` ### identify Upserts the contact. Pure projection: it never writes an event and never fires a program. | Field | Type | Required | Notes | | ------------ | ------------ | ----------------------------------------------- | -------------------------------------------------------------- | | `type` | `"identify"` | yes | | | `userId` | string | at least one of `userId`, `externalId`, `email` | Your stable user id. | | `externalId` | string | | Same meaning as `userId`. If both are sent, `externalId` wins. | | `email` | string | | Must be a valid email address. | | `name` | string | no | Display name. | | `traits` | object | no | Custom attributes, flat scalars only. See sanitization below. | ### track Records an event against a contact and fires any matching programs. | Field | Type | Required | Notes | | --------------------------------- | --------- | ----------------- | ----------------------------------------------------------------------------------- | | `type` | `"track"` | yes | | | `event` | string | yes | The event type, 1 to 120 characters. See naming below. | | `userId` / `externalId` / `email` | string | send at least one | Same identity rules as identify. A track with no identity is skipped, not an error. | | `properties` | object | no | Event details, flat scalars only. Same sanitization as traits. | | `timestamp` | string | no | ISO 8601. Defaults to arrival time. Invalid values fall back to arrival time. | | `messageId` | string | no | Your idempotency key for this event. Strongly recommended. | ### Identity resolution `externalId` (or `userId`) is the contact's primary identity; `email` matches or creates the contact when no external id is sent. Send the same `userId` from signup onward and Mara keeps one contact per user, even if the email changes later. Contacts that arrive with an email get lifecycle consent recorded automatically, so program sends are not blocked downstream. ### Traits and properties sanitization `traits` and `properties` become contact attributes and event details that Mara's agents can reference in copy, so they are filtered at the door: - Flat objects only. Nested objects and arrays are dropped. - Values must be strings, finite numbers, or booleans. Strings are trimmed and truncated at 1024 characters. - Keys: up to 64 characters from letters, digits, `_`, `.`, `:`, `-`. At most 50 keys survive per object. - Keys that look like secrets or sensitive PII (password, token, api_key, ssn, card numbers, and similar) are dropped outright. Do not send secrets. ## Idempotency and retries Set `messageId` on every track op: a UUID, or the id of the row in your own event log. Retrying a request with the same `messageId` is safe; the duplicate op returns `"status": "duplicate"` and writes nothing. Identify ops are upserts and naturally safe to retry. ## Rate limits 600 requests per hour per tenant, token bucket, burst up to 600. A batch of 100 operations counts as one request, so batching gives you up to 60,000 events per hour. Over the limit you get a 429 with a `Retry-After` header in seconds. Back off and retry after that. ## Responses Success is a 200 with one result per operation, in order: ```json { "ok": true, "results": [ { "index": 0, "type": "identify", "status": "ok", "contactId": "9a1f..." }, { "index": 1, "type": "track", "status": "ok", "contactId": "9a1f..." } ] } ``` Per-op `status` values: `ok`, `skipped_no_identity` (the op carried no usable identity), `duplicate` (the `messageId` was already processed). Errors return `{ "ok": false, "code": "...", "message": "..." }`: | HTTP | `code` | Meaning | | ---- | ------------------ | ------------------------------------------------------------------------- | | 400 | `bad_request` | Body is not valid JSON or fails the schema. | | 401 | `unauthorized` | Missing or wrong bearer key. | | 412 | `no_ingestion_key` | No key has been generated for this tenant yet. | | 429 | `rate_limited` | Over the hourly cap. Honor `Retry-After`. | | 500 | `infra` | Something broke on Mara's side. Safe to retry with the same `messageId`s. | ## How events fire programs Event types are free-form. Two ways they connect to programs: 1. **The signup event.** On the same settings row, tell Mara which event means "a new user signed up" (for example `user.signed_up`). Saving it seeds a draft welcome program that fires on that event; you approve the draft from your dashboard to make it live. 2. **Any other event.** Ask Mara in chat. "When a user fires `project.created`, start the activation program" is enough; she drafts the program with an on-event trigger and you approve it. Naming guidance: lowercase, dot-namespaced, object.action. `user.signed_up`, `project.created`, `report.exported`. Allowed characters are letters, digits, spaces, `.`, `_`, `:`, `-`, `/`, up to 120 characters. Keep types low-cardinality: no user ids or timestamps inside the type string. Details belong in `properties`. ## Quickstart Test with curl (the endpoint URL and key come from your settings page): ```bash curl -X POST "https://hiremara.com/api/tenants/{tenantId}/events" \ -H "Authorization: Bearer $MARA_INGESTION_KEY" \ -H "Content-Type: application/json" \ -d '{ "batch": [ { "type": "identify", "userId": "u_42", "email": "ada@example.com", "name": "Ada" }, { "type": "track", "event": "user.signed_up", "userId": "u_42", "messageId": "test-001" } ] }' ``` A minimal Node helper: ```js const MARA_EVENTS_URL = process.env.MARA_EVENTS_URL; // from your settings page const MARA_INGESTION_KEY = process.env.MARA_INGESTION_KEY; export async function maraSend(ops) { const res = await fetch(MARA_EVENTS_URL, { method: 'POST', headers: { Authorization: `Bearer ${MARA_INGESTION_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ batch: ops }), }); if (!res.ok) throw new Error(`Mara API ${res.status}: ${await res.text()}`); return res.json(); } // At signup: await maraSend([ { type: 'identify', userId: user.id, email: user.email, name: user.name }, { type: 'track', event: 'user.signed_up', userId: user.id, messageId: `signup-${user.id}` }, ]); ``` Call Mara off the request path (a queue, a background job, or at minimum fire-and-forget with a catch). An email platform should never be able to slow your product down. ## Verify it landed Three checks, in order: 1. The HTTP response: 200 with `"status": "ok"` per op. 2. Settings, Integrations: the ingestion health strip shows per-connector contact counts and last activity. 3. Ask Mara in chat: "did you get my test event?" ## For AI coding agents If you are an agent implementing this integration, the checklist: 1. Put the endpoint URL and ingestion key in env vars (`MARA_EVENTS_URL`, `MARA_INGESTION_KEY`). Never hardcode the key; never expose it client-side. 2. Add a small server-side helper that POSTs `{ batch: [...] }` with the bearer header. Batch when you can, up to 100 ops. 3. On signup: send one `identify` (userId, email, name, useful traits) plus one `track` with the agreed signup event type. 4. Instrument the 3 to 5 lifecycle moments that matter (activation milestone, key feature used, plan limit reached). Stable dot-namespaced event types, details in `properties`. 5. Set a deterministic `messageId` per event so retries are safe. Retry on 429 (honor `Retry-After`) and on 5xx; do not retry 4xx. 6. Keep Mara off the hot path: queue or fire-and-forget. A Mara outage must not break signup. 7. Verify with the curl above, then confirm in the response that every op returned `"status": "ok"`. --- # Webhooks: Stripe, Polar, Clerk Billing and auth events reach Mara through the webhooks you already have. Each connector gets a per-tenant URL, verifies the provider's signature, and dedupes on the provider's event id, so redeliveries are safe. Setup is two pasted values: Mara's URL into the provider, the provider's signing secret into Mara. Your per-tenant URLs and the secret fields live in Settings under Integrations. The raw markdown version of this page is at [hiremara.com/docs/webhooks.md](https://hiremara.com/docs/webhooks.md). For product events from your own code, see the [Mara API](/docs/api). ## What programs can trigger on Provider events are normalized into eight lifecycle moments. Programs trigger on these, not on raw provider payloads: | Mara event type | Meaning | | ----------------------- | ------------------------------------------------ | | `subscription-started` | A new subscription begins. | | `trial-converted` | A trial becomes a paying subscription. | | `subscription-upgraded` | Plan or quantity changed upward. | | `subscription-canceled` | Subscription canceled or revoked. | | `payment-failed` | A renewal payment failed (dunning territory). | | `payment-recovered` | A previously failing payment went through. | | `refund-issued` | A charge was refunded. | | `purchase` | A one-time purchase, not tied to a subscription. | Anything else the provider sends returns `200` with `"status": "ignored"`. It is fine, and simplest, to send everything. Custom fields you attach as provider metadata (Stripe subscription or checkout metadata, Polar order or customer metadata, Clerk public metadata) are projected onto the contact as attributes, with the same sanitization as the Mara API: flat scalars only, secret-looking keys dropped, capped at 50 keys. ## Stripe Endpoint: ``` POST https://hiremara.com/api/webhooks/stripe/{tenantId} ``` Setup: 1. In the Stripe dashboard, open Developers, then Webhooks, and add a destination with your per-tenant URL from Mara's settings page. 2. Select these events (or send all): `customer.subscription.created`, `customer.subscription.updated`, `customer.subscription.deleted`, `invoice.payment_failed`, `invoice.payment_succeeded`, `charge.refunded`, `checkout.session.completed`. 3. Copy the signing secret (`whsec_...`) and paste it into Settings, Integrations, Billing, Stripe. How Stripe events map: | Stripe event | Becomes | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `customer.subscription.created` | `subscription-started` | | `customer.subscription.updated` | `trial-converted` when status goes trialing to active; `subscription-upgraded` when the plan or items changed; otherwise ignored. | | `customer.subscription.deleted` | `subscription-canceled` | | `invoice.payment_failed` | `payment-failed` | | `invoice.payment_succeeded` | `payment-recovered`, only when it recovers a failing invoice. First-attempt successes are ignored. | | `charge.refunded` | `refund-issued` | | `checkout.session.completed` | `purchase`, only for `mode=payment` (one-time). Subscription checkouts are already covered above. | Requests are verified with the `stripe-signature` header against your pasted secret. Wrong or missing signature returns 401; a tenant with no secret configured returns 412. ## Polar Endpoint: ``` POST https://hiremara.com/api/webhooks/polar/{tenantId} ``` Setup: 1. In Polar, open your organization settings, then Webhooks, and add an endpoint with your per-tenant URL. 2. Select the subscription and order events (or send all). 3. Copy the signing secret and paste it into Settings, Integrations, Billing, Polar. How Polar events map: | Polar event | Becomes | | ----------------------------------------------- | ----------------------------------------------------------------------------------- | | `subscription.created` | `subscription-started` | | `subscription.active` | `trial-converted` | | `subscription.upgraded` | `subscription-upgraded` | | `subscription.canceled`, `subscription.revoked` | `subscription-canceled` | | `subscription.past_due` | `payment-failed` | | `subscription.recovered` | `payment-recovered` | | `order.refunded` | `refund-issued` | | `order.paid` | `purchase`, only for orders not tied to a subscription. Renewal cycles are ignored. | Signatures follow the Standard Webhooks spec (`webhook-id`, `webhook-timestamp`, `webhook-signature` headers). ## Clerk Endpoint: ``` POST https://hiremara.com/api/webhooks/clerk/{tenantId} ``` Setup: 1. In the Clerk dashboard, open Webhooks and add an endpoint with your per-tenant URL. 2. Subscribe to `user.created`, `user.updated`, and `user.deleted`. 3. Copy the Svix signing secret and paste it into Settings, Integrations, Clerk. What each event does: `user.created` creates the contact and records a `user.created` event, which can fire your welcome program (map it as the signup event on the settings row). `user.updated` refreshes the contact's email and name. `user.deleted` records a deactivation signal. Mara projects the email, username, avatar URL, and public metadata; private and unsafe metadata are never read. Optional backfill: paste a Clerk Backend API key on the same settings row and Mara imports your existing users as contacts, so programs do not start from an empty list. ## Verify it is flowing After setup, trigger a test event (most providers have a "send test event" button) and check the ingestion health strip in Settings, Integrations: it shows per-connector contact counts and last activity. Or ask Mara in chat. --- # MCP server Connect your AI tools, Claude Code, Claude Desktop, Cursor, or anything else that speaks MCP, straight to your Mara workspace. Your agent can read your programs, drafts, sends, and Playbook, and act on your behalf: draft a program, approve a send, pause something that is not working. It runs under the same guardrails as your dashboard chat. This page is the complete spec, written for humans and for AI coding agents. The raw markdown lives at [hiremara.com/docs/mcp.md](https://hiremara.com/docs/mcp.md). The fastest path: open Settings, then Integrations, then MCP (AI tools) in your dashboard, generate a key, and copy the ready-made connect command. ## What it is `POST /api/mcp` is a remote MCP server over Streamable HTTP. Every call authenticates, resolves your workspace, runs one tool, and returns. There is no separate session to manage; each request carries your key and stands on its own. ## Authentication Auth is a per-workspace key with the prefix `mara_mcp_`, generated from Settings, Integrations, MCP (AI tools). The raw key is shown exactly once at generation; Mara stores only a hash. You can hold several live keys at once, one per machine or agent, and revoke any of them without touching the others. Send it as a bearer token: ``` Authorization: Bearer mara_mcp_... ``` This is a credential for your own tools, not a public API. Keep it out of source control the same way you would an API key for any other service. ## Connect Claude Code ```bash claude mcp add --transport http mara https://hiremara.com/api/mcp --header "Authorization: Bearer " ``` Run it once from anywhere; Claude Code remembers the connection. Your settings row's copy button fills in your real key. ## Connect Claude Desktop Add an entry to your MCP config (Settings, Developer, Edit Config in Claude Desktop): ```json { "mcpServers": { "mara": { "url": "https://hiremara.com/api/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Restart Claude Desktop after saving. ## Connect Cursor Cursor reads the same shape. Add it under Settings, MCP: ```json { "mcpServers": { "mara": { "url": "https://hiremara.com/api/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ## The approval promise Nothing sends to a customer without approval in your dashboard queue, unless your own policy gate says otherwise (for example, a reply-autonomy setting you turned on yourself). Drafting tools call a model and can take up to a minute or so to return; everything else is a fast read or a direct database action. A drafted email lands `pending_approval` exactly the same way it would from chat: you approve it, or Mara's autonomy setting does, never the tool call by itself. ## Connect your product If you self host, or you have no CRM connected, the fastest way in is to hand your coding agent one instruction: set up the Mara API for me. Two tools close the loop end to end, in one conversation, without you ever opening Settings: 1. `setup_events_ingestion` mints your ingestion key (or reports its status if one already exists), hands your agent the exact endpoint URL, and optionally maps which event means "a new user signed up." 2. Your agent writes the integration, using the linked spec at [/docs/api](/docs/api). 3. `check_recent_events` confirms the test event your agent fires actually landed, with a per-connector health summary, so you get a "done, verified" report instead of a "should be working" guess. Both tools are MCP-only: they never appear in your dashboard chat, since chat is not the place for a raw ingestion key to surface. ## Tools Ten tools only ever read: | Tool | What it does | | ---------------------- | ------------------------------------------------------------------------------------------------------------ | | `list_pending_drafts` | List email drafts awaiting your approval. | | `list_active_programs` | List programs currently active or paused. | | `list_draft_programs` | List programs awaiting your approval, with enough detail to approve one directly. | | `list_segments` | List saved segments with current sizes. | | `list_learnings` | List entries from the Learning Ledger, Mara's Playbook. | | `list_sent` | List recent emails from the send queue, with status and failure reasons. | | `contact_send_history` | Everything one contact has been sent or has queued, across all programs. | | `get_program_detail` | Inspect one program's steps, copy, and live variant arms in depth. | | `get_journey_spine` | Read your product journey state spine (funnel stages), in order, with each state's confirmed inbound events. | | `get_domain_status` | Read your sending domain's name, status, DNS records, and whether the send-from mailbox is provisioned. | Twenty-three tools act, each holding to the same approval promise above: | Tool | What it does | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | `approve_draft` | Approve one pending email draft so it can send. | | `reject_draft` | Reject one pending email draft so it will not send. | | `draft_program` | Draft a new event-entry program for you to approve. | | `draft_segment_program` | Draft a new program that targets an existing saved segment. | | `approve_program` | Activate a draft program so it starts firing. | | `edit_program` | Edit an existing program's steps, timing, or entry event. | | `pause_program` | Pause one active program. | | `resume_program` | Resume one paused program back to active. | | `archive_program` | Archive one program for good. | | `draft_segment` | Create a new saved segment from a plain-English description. | | `approve_segment` | Activate a proposed segment so it can be targeted. | | `add_learning` | Add an entry to the Learning Ledger. | | `retire_learning` | Retire an entry from the Learning Ledger. | | `add_suppression` | Add an email address to the suppression list. | | `rewrite_variant` | Fix a program variant whose copy keeps failing to send. | | `retire_variant` | Retire one program variant; the bandit shifts send-share to the rest. | | `dismiss_held_sends` | Clear held sends (permanently failed, never retried) from the Activity feed. | | `configure_journey_spine` | Add, rename, reorder, or remove states on your product journey spine, set a state's kind, and set the goal. | | `set_event_mapping` | Confirm or reject what one event means: which state it advances a contact into, or that it is not a step. | | `register_sending_domain` | Register your sending domain and get back the DNS records to add. | | `set_email_appearance` | Set your signature logo and the accent color for your single filled CTA button. | | `capture_founder_voice` | Hand Mara 1-3 real emails you wrote so she can distill and draft in your real voice. | | `refire_contact_into_program` | Re-enter one contact into a program by re-firing its entry event for them, to recover someone who genuinely missed it. | `configure_journey_spine` shapes the state spine container only, the funnel stages themselves, not what any event means. Confirming or rejecting what an event means used to be a founder-only decision on the Programs page. It no longer is: `set_event_mapping` lets your agent make that call directly, on your explicit instruction, the same trust model as `approve_program` or `pause_program`. It appends to the same append-only mapping log the Programs page confirm UI writes to, so the latest decision always wins, and nothing is ever silently edited or removed. `register_sending_domain` registers through the exact same path the dashboard domain page uses, so it never silently replaces a live domain: registering the same domain again just hands back the existing records, and a different domain already on file is refused with a note that changing it is a dashboard action. It also refuses, without registering anything, if the exact domain is already registered to a DIFFERENT Mara workspace, since domain identity isn't shared across workspaces; that refusal never names or otherwise identifies the other workspace. `set_email_appearance` is a partial update: every field is optional and whatever you omit keeps its current saved value. A too-light accent color is accepted and saved rather than rejected, exactly like the Settings editor, since the actual guard is a render-time fallback to a neutral dark button fill, not a save-time rejection. `capture_founder_voice` takes raw writing samples only: 1-3 real emails, pasted as-is, plus an optional short note. There is no field for formality, cadence, or any other trait of your voice; Mara infers all of that herself from the samples. It returns only a plain-language summary of what she learned, never the underlying fingerprint. A missing model or a failed distillation returns a clean error and never touches any voice you already captured. `refire_contact_into_program` is a real action, not a diagnostic: on success it can result in a real email being drafted and sent to the contact you name, through the exact same pipeline a genuine signup uses. Use it only to recover someone who genuinely missed a program, for example an ingestion failure that swallowed their original signup event. It mints a fresh identity for every call, so calling it twice for the same contact fires twice rather than silently doing nothing the second time; only call it once per contact you mean to recover. It refuses plainly, and never claims a send happened, when the contact is already partway through the program, already received that step, suppressed, or the program has no matching entry trigger. One tool is Mara herself: | Tool | What it does | | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ask_mara` | Hand Mara a question or an instruction and get her real answer back, run through the same model, system prompt, and tool loop as your dashboard chat companion. The turn is saved into your real chat history, so it shows up in your dashboard too. | Two tools set up and verify your own product's event integration. They are MCP-only: they never appear in your dashboard chat, since a raw ingestion key has no business surfacing there. | Tool | What it does | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | | `setup_events_ingestion` | Mint your Mara API ingestion key (or report its current status), hand back the exact endpoint URL, and map your signup event. | | `check_recent_events` | Confirm recent events actually arrived, with event type, timing, contact identity, and a per-connector health summary. | ### If you connected before August 2026 The email-sequence tools used to be named `*_journey`: `draft_journey`, `approve_journey`, `edit_journey`, `pause_journey`, `archive_journey`, `resume_journey`, `list_active_journeys`, `list_draft_journeys`, `get_journey_detail`, `draft_segment_journey`, `refire_contact_into_journey`. We renamed them to `*_program`, because a **program** is the email sequence Mara runs and a **journey** is now only ever your customer's path through your product. The full mapping is in the [glossary](/docs/glossary). Every old name still works, so an agent mid-session does not break. They are marked deprecated in the tool list and will be removed in a future release, so prefer the `*_program` names in anything you save. `get_journey_spine` and `configure_journey_spine` were **not** renamed: they operate on the customer journey, which is still called a journey. ## Rate limits The endpoint allows 60 calls per minute per key. `ask_mara` is stricter on top of that: 10 calls per minute per key, and 200 per day per workspace, since each call is a real model turn rather than a cheap read. Over a limit you get a clean tool error naming the wait, not a broken connection. ## Verify it landed Ask your agent to call `list_active_programs` or `list_pending_drafts` first. A working connection returns your real workspace data immediately; a wrong or revoked key returns an authorization error before anything else runs. ## For AI coding agents If you are an agent setting this up for a founder, the checklist: 1. Tell the founder to generate a key from Settings, Integrations, MCP (AI tools), and copy it into your config or the connect command. Never ask for it in plain chat if a copy button is available. 2. Register the server with the client the founder is using (Claude Code, Claude Desktop, Cursor) using the blocks above. 3. Confirm the connection with a read-only call (`list_active_programs` is a good first check). 4. If the founder self hosts or has no CRM connected, call `setup_events_ingestion` to mint their key and get the exact endpoint URL, write the integration against [/docs/api](/docs/api), then call `check_recent_events` after firing a test event to confirm it landed. Never mint a second key with `rotate: true` on a routine check; that revokes the founder's live key. 5. Remember every action tool still lands `pending_approval` in the dashboard, or waits on the founder's own autonomy setting. Do not tell the founder something "sent" because a tool call returned; check `list_sent` or the dashboard for the real outcome. 6. Treat every key like any other credential: one per machine, revoked the moment a machine is retired. --- # Glossary If you already run lifecycle email somewhere else, you know all of this. You just call it something else. Here is the whole vocabulary, mapped. ## The short version | If you say | Where you say it | Mara calls it | | ------------------------------- | ------------------------------ | -------------------- | | loop | Loops | program | | flow | Klaviyo | program | | sequence | Sequenzy, Encharge | program | | campaign (an automation) | Customer.io | program | | campaign, broadcast (a one-off) | Loops, Klaviyo, Resend | nothing, she doesn't | | audience (your whole list) | Loops | contacts | | segment | Customer.io, Klaviyo, Encharge | segment | | subscriber, profile | most tools | contact | | goal | Loops, Customer.io | goal | | A/B test, split test | most tools | variants | ## The terms, in full **Program.** One lifecycle email sequence Mara runs end to end: the trigger that starts it, the emails, the waits between them, the branches. A welcome series is a program. So is a win-back. This is also the billing unit, which is why the word is on the pricing page: Starter runs three at once, Growth runs ten. Your tool probably calls this a flow, a loop, a sequence, or a campaign. **Customer journey.** The path a customer walks through your product: visitor, signed up, activated, paid, retained. It is not an email artifact. It is the thing programs hang off. Mara draws it as a map, you edit the states to match your product, and you mark one as your goal. Most sending tools have no equivalent, because most sending tools do not model your product at all. **State.** One stage on that journey. "Activated" is a state. **Goal.** The one state you are working toward. It is your value metric. Loops and Customer.io both shipped a feature called Goals in 2026 and it means roughly the same thing here. **Segment.** A group of contacts matched by rules. Same word Customer.io, Klaviyo, Encharge and Userlist use. One warning if you are coming from Loops: Loops uses "audience" for your entire contact list. Mara does not use that word at all, precisely because it means two different things depending on where you last worked. Everyone in your account is your **contacts**. A rules-matched slice of them is a **segment**. **Contact.** A person. Not a subscriber, because they are a person using your product, not a person on a mailing list. The distinction matters for the bill: contacts are unlimited on both plans, so a dormant signup costs nothing and stays available for the win-back you have not written yet. **Email.** One message to one recipient. **Send** is the act of delivering one. **Step.** One email inside a program. **Variants.** The alternative copies Mara writes for a single step and tests against each other on live sends. Your tool calls this an A/B test. The difference is who does it: she writes the variants, splits the sends, reads the results, shifts share to the winner, and rewrites the loser without being asked. **Reply.** An inbound message from a contact. Mara reads it, classifies it, and drafts an answer. ## The words we don't use **Campaign.** Genuinely ambiguous. At Customer.io it means an automation. At Loops, Klaviyo and Resend it means a one-off blast. Context cannot disambiguate it, so it is not in the product anywhere. **Broadcast, newsletter.** Not vocabulary, product scope: Mara only writes triggered programs. If your main sending job is a Tuesday newsletter, she is the wrong hire and the [comparison pages](/compare) say so. **Flow.** Klaviyo's word for a program. Avoided so "program" always means one thing. ## The parts with no equivalent anywhere These are the ones worth reading, because no tool you have used has them. **Needs you.** The approval queue, and your home page. Every email Mara writes lands here as pending approval before it can send. This is the part that surprises people most, so it is worth being blunt about it: **every other tool goes prompt, configured, live.** Mara drafts and then stops. If you have just arrived and it looks like nothing is sending, that is not a setup problem. Your programs are running. They are waiting on you. New accounts cannot skip the first approval, and win-back, churn-save and expansion always come back for review even after you switch on autopilot. **Playbook.** The Learning Ledger: what Mara has worked out about your program, written down with the evidence, and applied to future drafts. It fills up as you correct her. **Customer Voice.** Themes mined from what your customers actually wrote back, quoted verbatim, ranked, exportable, with a "mark shipped" that drafts the you-asked-we-built-it email. **Verdict.** Whether a program is _proven_ to move your goal, measured against a held-back control group. Distinct from the funnel, which shows reach and is labeled as correlation. ## Still stuck on a word Ask Mara in chat. She knows this vocabulary and will happily translate from whatever you used before. --- # Help center Short, practical guides to running your lifecycle email program with Mara. Each page opens with a quick walkthrough, then explains what you can do, how to do it, and where the limits are. Mara is hired, not installed. You approve the work; she drafts, sends, and improves the emails. These pages cover the surfaces where that happens. ## Topics - [Dashboard](/help/dashboard): the sidebar pages and the chat companion, and what each one is for. - [Programs](/help/programs): what a program is, how to see what each one sends and to whom, and how to pause, resume, or archive one. - [Chat](/help/chat): how to ask Mara to build, edit, and approve programs and segments, and what she can and cannot do from the conversation. - [Playbook](/help/playbook): what Mara has learned about writing to your customers, confidence tiers, sources, and how it shapes her drafts. - [Settings](/help/settings): a reference to every settings section, from brand profile and value metric to send window, reply autonomy, and suppression. If something here is missing or unclear, tell us from the Feedback button in your dashboard. ## For AI assistants Every help page has a raw markdown twin: append `.md` to the URL. The site root also serves [llms.txt](https://hiremara.com/llms.txt) and [llms-full.txt](https://hiremara.com/llms-full.txt). --- # Dashboard Your dashboard is where you work with Mara day to day. It opens with one question in mind: does Mara need anything from you? Home answers that question alone. Programs, Activity, Results, Contacts, Playbook, and Voice are your reference pages, reached from the sidebar. Chat sits alongside every page as a companion you can dock, float, or tuck away, so directing Mara never means leaving the page you are on. ## What you can do - Land on Home and see in one glance whether Mara is waiting on you. Its eyebrow tells you the state: waiting on you with a count, a fix needed, or all clear. Home collects everything that needs your decision: blockers that stop her working, customer replies where a person is waiting, emails and programs she has drafted for your approval, and optional ideas she suggests. - Read the running history of what Mara has done on the Activity page: emails sent, programs activated, replies handled, learnings added. It is a log, so nothing there asks you to act. - Check whether the program is working on the Results page: your value metric over time, per-program funnels, top emails, and deliverability. - Direct Mara from chat, wherever you are in the dashboard: ask her to design a program, edit copy, build a segment, or explain anything. See the [Chat guide](/help/chat) for how that works. - Reach your reference pages from the sidebar: Programs (what each one sends), Contacts (who is in your program), Playbook (what Mara has learned), Voice (what your customers are telling her), and Settings (everything you configure). ## How The sidebar on the left lists every page: Home, Programs, Activity, Results, Contacts, Playbook, Voice, and Settings. Click any one to open it full width. Chat is not a page. It is a companion that stays with you across the dashboard, in one of three states: docked beside the page, floating over it, or minimized to a small bubble you reopen when you want it. - Work top to bottom on Home. Items are tiered by urgency, with blockers first and optional ideas last. Acting on an item clears it from the queue. When there is nothing left you see "Nothing needs you. Mara is working." - Approving and rejecting happen on the cards on Home, using the same plain verbs everywhere: Approve and send for an email, Approve and activate for a program, Reject to drop a draft, Dismiss to hide an idea. - Activity and Results are read only. Expand a row in Activity to read the full detail; on a failed send you can hand the context to chat with "Ask Mara about this". - Use the sidebar to open Programs, Contacts, Playbook, Voice, or Settings when you want to look something up, and the tenant card at the bottom of the sidebar to switch between companies. ## Limitations - Home is for decisions, not browsing. Once you act on an item it leaves the queue, by design. To revisit something later, look in Activity or on the relevant page. - Activity never carries action buttons. It is a record of what happened. Anything you can act on lives on Home, with the Activity row as its echo. - Results reports aggregates over a time window, not row-level actions. Where a number is a stand-in for what you really care about, the label says so. - Building and editing happen in chat, not on the reference pages. Those pages surface and summarize; the work itself is a conversation with Mara. - The dashboard shows your own workspace only. It never exposes another company's data. --- # Programs A program is one lifecycle email sequence. A welcome series, a win-back, a dunning sequence for failed payments. Each program has a trigger that starts it (a new signup, a canceled subscription, entry into a segment), one or more email steps, and timing between them. Mara runs every program for you. You decide which ones go live. ## What you can do - See every program Mara runs for you, with its status, what starts it, how many steps it has, and how much it has sent in the last 30 days. - Open any program to read exactly what it sends, to whom, and when: the segment, each step with its trigger and timing, the latest email copy, and the last 30 days of results for that program. - Where a step is testing variants, see the live versions and the share of sends each one is getting as Mara learns which lands best. - Pause a live program so it stops sending, resume a paused one, or archive a program you no longer want. - Ask Mara in chat to design a new program, change copy or timing, or set up a whole program. ## How The Programs pages live behind the Programs item in your dashboard sidebar. - The list page shows all of your programs. Click any one to open its detail page. - The detail page lays out the segment, the funnel for the last 30 days, and each step in order with its trigger, timing, and the latest email. - Pause, Resume, and Archive are buttons on the program, so a quick state change does not need a conversation. A live program can be paused; a paused program can be resumed; any program can be archived. Archiving asks you to confirm first. - Anything that changes what a program says or when it sends happens in chat, the place where Mara does the work. Open chat and tell her what you want. See the [Chat guide](/help/chat) for how that works. ## Limitations - The Programs pages are for reading and for mechanical state changes (pause, resume, archive). They do not let you edit copy or timing in place. Those edits go through chat so Mara can redraft and you can re-approve. - Resuming a program re-runs the same checks as going live. If another live program already starts on the same trigger, Mara will not resume into that collision. Pause or archive the other one first. - One trigger should drive one live program. Mara refuses to put two live programs on the same trigger so a contact never gets two emails for the same moment. - A program only sends once it is live and your sending domain is set up. A drafted or paused program sends nothing. - These pages show your own programs only. They never expose another company's data. --- # Chat Chat is how you direct Mara. It is a conversation in your dashboard where you ask her to design programs, write and edit emails, build segments, approve or reject her drafts, and teach her what works. She streams a reply, and when she takes an action she shows it inline so you can see what changed. ## What you can do - Ask Mara to design a program for any moment in your customer lifecycle, or to set up a whole program. She drafts it and you approve before anything goes live. - Edit an existing program: change the copy, the timing, the segment, or the trigger. Every edit comes back to you to re-approve. - Build a segment from your contacts and their behavior, then attach a program to it. - Approve or reject what Mara has drafted, including programs and the variant sets she proposes for testing. - Pause, resume, or archive a program from the conversation. - Manage your Playbook, the set of learnings that shape how Mara writes. Ask her what she has learned, add a learning, or retire one. - Fix a send problem without leaving chat: rewrite or retire an email variant, add a suppression, or clear failed sends. - Ask what is happening: which programs are active, what has been sent, and why a send failed. ## How Open chat from anywhere in your dashboard (it docks beside the page, floats over it, or tucks into a small bubble, whichever you prefer) and type what you want, in plain language. You do not need to name a tool or learn any syntax. Mara figures out what to do. - When she takes an action, it appears inline in the conversation as a collapsible step, so you can expand it to see exactly what she did. - Actions that change what gets sent are gated. Mara drafts, and the draft waits for your approval before it sends. You stay in control. - Some cards elsewhere in the dashboard hand you off to chat with the context already filled in, for example an idea from Mara or a failed send you want to ask about. Approving from there runs the same conversation. - Long conversations stay coherent: Mara works from a running summary of the earlier messages plus your most recent ones. Start a new chat anytime for a clean slate, and use the history dropdown to jump back into a past conversation. ## Limitations - Chat does not send data into Mara. Connecting your product (who your users are and what they do) happens through the Mara API and webhooks, covered in the [developer docs](/docs). - Mara will not skip your approval on anything that sends. She drafts; you decide. Approving is always a deliberate step. - She acts only on your own workspace. She cannot see or touch another company's contacts, programs, or data. - Mara reaches for a tool before she tells you she cannot do something. If she says a request is out of scope, it is because no tool covers it yet, not because she did not look. - Chat is for directing the program. To read what a program sends step by step, the [Programs pages](/help/programs) lay it out without a conversation. --- # Playbook Your Playbook is what Mara has learned about writing to your customers. As she sends emails, reads replies, and watches outcomes, she distills the signal into short, evidence-cited learnings: what subject lines land, what tone fits your segment, when to send, what to say. The Playbook is that running set of insights, and Mara uses it when she writes for you. ## What you can do - Read what Mara has learned, grouped by category: voice, subject lines, timing, customers, structure, and offers. - See how sure she is about each learning. Every learning carries a confidence tier, from a hypothesis she is still testing to a validated insight backed by your own results. - See where a learning came from. A learning is either one you taught Mara or one she distilled from your data, and each row is labeled so you can tell. - Open the evidence behind a learning. Distilled learnings cite the real sends, replies, and outcomes they came from, so nothing is a black box. - Add a learning, retire one, or ask what she knows, all from chat. See the [Chat guide](/help/chat). - Turn off applying learnings in Settings if you want Mara to keep watching and noting without changing her drafts yet. ## How The Playbook lives behind the Playbook item in your dashboard sidebar. - Active learnings are grouped by category at the top, each with its confidence tier, its source, and how many times it has been applied. Retired or contradicted learnings sit in a collapsed history section below. - Mara builds the Playbook on her own as your results come in. You do not have to do anything to start it. A learning you add yourself in chat sits alongside the ones she distills. - When applying learnings is on, the default, Mara folds the relevant learnings into every email she writes. The validated ones shape her drafting directly. - Toggle "Apply Playbook learnings" in Settings to switch between using the Playbook in drafts and observe-only mode, where it keeps building but does not change her copy. ## Limitations - The Playbook fills in over time, not on day one. Mara needs your sends, replies, and outcomes to have something to learn from, so a new workspace starts with little or nothing. - It is read on its page and managed in chat. The page is for reading; adding or retiring a learning is a chat action. - Mara holds the evidence bar high. She will not promote a learning to validated without your real data behind it, and she will not quietly overwrite a learning you taught her. - A learning can be contradicted later. When new results disagree with an old insight, Mara moves it to history rather than pretending it still holds. - Your Playbook is yours alone. It is built only from your data and never mixes in another company's results. --- # Settings Settings is where you configure how Mara works for your company. This page is a quick reference to every core section. Reach Settings from the Settings item in your dashboard sidebar. It is grouped into five pages, so you only ever read the handful of settings you came for: **Brand**, **Sending**, **Integrations**, **How Mara works**, and **Account**. Switch between them from the list on the left of the Settings page; inside a group, the same list links to each section on that page. Most changes take effect on the next email Mara writes or the next worker scan. ## Brand Who you are, how you sound, and how your emails look. ### Brand Profile The voice and product context Mara uses for every email she writes: your tone, a sample line that sounds like you, your value prop, your ideal customer, and the features she is allowed to reference. It also holds who emails are signed by and the mailing address that marketing email is required to carry. Mara fills this in from your website, and you correct it here. Changes apply to the next email she writes. ### Your Voice The real writing voice Mara learned from emails you pasted, shown read-only: a plain summary of how you write, the fingerprint she distilled, and the excerpts she models. You can recapture it by pasting fresh samples, or clear it to fall back on the voice from your marketing site. You supply the samples and Mara distills them; you never hand-edit her reading of your voice. ### Email Appearance How your emails look: your logo in the signature, an accent color, and the size of the signature logo. A live preview renders a sample email as you change each control, so you see the result before you save. ### Re-scrape Website Re-runs Mara's brand analysis so she updates her snapshot of you. Editing Brand Profile above already covers the day-one workflow. ## Sending Where your email comes from, when it goes out, and who is excluded. ### Send From The address Mara sends from, and where replies come back. You choose the local part on your verified sending domain. Register a sending domain first, since the address sits on it. If a mailbox is already live, a new address takes effect the next time Mara provisions, not as a live rename. ### Send Window When Mara is allowed to send, plus the most emails one contact gets in a week. Set your timezone and a per-contact weekly cap; the cap defaults to 3 per week, and 0 disables it. On top of the cap, Mara sends at most one program email per contact per day and still respects the deliverability fatigue gate. It applies on the next worker scan. ### Suppression Addresses Mara must never email again. Paste an email and pick a reason, and Mara skips it from then on. This is add-only; it is your escape hatch for an address you know should not hear from you. ### Segments The saved segments Mara can target with programs, shown as a read-only list with live sizes and a proposed or active badge. Mara proposes segments from your product activity; to build one, ask her in chat. ## Integrations The connections Mara reads your product and your billing through. The external systems Mara reads from or writes to: your sending domain, GitHub, billing webhooks from Stripe or Polar, the Mara API, Clerk, Supabase, and Molted. This is also where you connect a product so Mara learns who your users are and what they do, and where an ingestion-health strip shows per-connector contact counts. Connecting your product is covered in the [developer docs](/docs). ## How Mara Works What Mara decides on her own, and what she brings to you first. ### Mara's Playbook Whether the lessons in your [Playbook](/help/playbook) steer the copy she writes. Leave it on and Mara applies what she has learned about your program to every new draft. ### Reply Autonomy How much Mara can send a reply on her own, set per kind of inbound. She drafts every reply regardless; this decides which ones she sends without waiting for you. Each kind can graduate from "always ask me" to auto-send only after enough approvals, so she learns your voice first. Some kinds, like complaints, legal, and unsubscribes, always wait for you and cannot be changed. ### Value Metric The single number Mara optimizes for and reports on in Results. It is shown read-only here: your goal is the goal state on your journey map, so you set it there and this section reflects it. ### Roadmap and Coming Soon Recently shipped features and what is coming next, so Mara can reference real work in win-back and re-engagement emails instead of speaking in generalities. Paste a list, or connect your GitHub repo from Integrations and let her keep it current. ## Account Your plan, and the controls that end it. ### Subscription Your Mara plan, Starter or Growth. You start a 7-day trial to activate programs and begin sending, then pay per active program with sends metered and overage shown. Sending is never blocked; you see usage and an overage estimate here, and "Manage billing" opens the customer portal. Your monthly send allotment is read-only here, by design. ### Danger Zone Delete this company. Deleting stops in-flight sends, pauses active programs, cancels pending emails and program drafts, cancels any active subscription, and removes your access. You confirm by typing the company name, and it is reversible only with support intervention.