EterMail API (v1)

Sync users and events from your server into an EterMail project. Fields follow the Segment spec; SaaS products and mobile apps both connect through this API.

OpenAPI spec, SDK and MCP server on GitHub ↗github.com/EterMail/etermail-api: the full API as OpenAPI 3.1, a zero-dependency JavaScript/TypeScript SDK, an MCP server for Claude and Cursor, and examples. Install the SDK with npm install @etermail/sdk; run the MCP server with npx -y @etermail/mcp.

Authentication

Create a server-side (sk_) key under Project settings → API keys. It is shown once and must only be used on your server, never in a browser or app. The key determines which project receives the data. Segment-style Basic auth also works (the key as username, empty password).

Authorization: Bearer sk_…

General rules

  • messageId is required and unique per project; a repeat returns {"ok":true,"duplicate":true}, so retries are safe.
  • timestamp is optional (ISO 8601), for backfilling history.
  • Provide userId (your user ID), email, or both; userId takes precedence as the identity.
  • 600 requests per minute per key; beyond that you get 429 with Retry-After. Request bodies up to 1 MB.

POST /api/v1/identify

Creates or updates a contact. firstName, lastName, locale and timezone in traits map to fixed fields (language or lang also set locale when locale is absent; tags like de or pt-BR); everything else becomes a custom attribute. consent is optional: subscribing requires evidence of when and how the person agreed, and the API cannot resubscribe someone who unsubscribed.

curl https://etermail.ai/api/v1/identify \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "u_123",
    "messageId": "4f9c…",
    "traits": { "email": "[email protected]", "firstName": "Ann", "plan": "pro" },
    "consent": { "topic": "marketing", "status": "subscribed",
      "evidence": { "form": "signup", "checkbox": true } }
  }'

POST /api/v1/track

Records an event for segmentation and attribution, and to trigger custom-event flows (for example, onboarding emails after a trial starts).

{ "userId": "u_123", "event": "Trial Started",
  "properties": { "plan": "pro" }, "messageId": "9a1e…" }

POST /api/v1/batch

Up to 500 identify / track calls at once, processed one by one with a results array; a failed item does not affect the others.

{ "batch": [
  { "type": "identify", "userId": "u_123", "messageId": "…" },
  { "type": "track", "userId": "u_123", "event": "Logged In", "messageId": "…" }
] }

Signup form submissions (public)

POST /api/forms/{publicId}/submit needs no key and lets your own website form submit directly; the request origin must be listed under the form's allowed websites. With double opt-in it returns check_email.