MOLTED EMAIL

Email Capture

One-call contact collection with list subscription and optional confirmation email.

Email capture handles the entire "collect an email" flow in one API call: upsert contact, subscribe to list, and optionally send a confirmation email. Covers waitlists, beta signups, newsletter captures, and lead magnets.

Endpoint

POST https://api.molted.email/v1/agent/capture

Basic usage

Silent capture (no email sent)

Collect an email address and subscribe to a list without sending any confirmation:

CLI
molted capture --email user@example.com --list waitlist
curl
curl -X POST https://api.molted.email/v1/agent/capture \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "list": "waitlist"
  }'

Response:

{
  "contactId": "uuid",
  "listId": "uuid",
  "subscriptionStatus": "active",
  "emailStatus": null,
  "requestId": null
}

With confirmation email

Add subject and html/text to send a confirmation:

CLI
molted capture --email user@example.com --list waitlist \
  --subject "You're on the waitlist!" \
  --body "<p>Thanks for signing up. We'll notify you when we launch.</p>" \
  --text "Thanks for signing up."
curl
curl -X POST https://api.molted.email/v1/agent/capture \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "list": "waitlist",
    "subject": "You'\''re on the waitlist!",
    "html": "<p>Thanks for signing up.</p>",
    "text": "Thanks for signing up."
  }'

Response:

{
  "contactId": "uuid",
  "listId": "uuid",
  "subscriptionStatus": "active",
  "emailStatus": "queued",
  "requestId": "uuid"
}

With tags and metadata

Enrich the contact record with tags and arbitrary metadata:

CLI
molted capture --email user@example.com --list beta-users \
  --name "Jane Smith" \
  --tags early-access,landing-page \
  --source form \
  --metadata '{"referrer": "producthunt"}'
curl
curl -X POST https://api.molted.email/v1/agent/capture \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "list": "beta-users",
    "name": "Jane Smith",
    "tags": ["early-access", "landing-page"],
    "source": "form",
    "metadata": { "referrer": "producthunt" }
  }'

Field reference

FieldRequiredDescription
emailYesRecipient email address
listYesList slug. Subscribes to this list; auto-creates it if it doesn't exist
subjectNoConfirmation email subject. If omitted, no email is sent (silent capture)
htmlNoEmail HTML body (required if subject is set)
textNoEmail plaintext body (fallback)
nameNoContact display name
tagsNoArray of string tags stored in contact metadata.tags (merged with existing)
doubleOptInNoIf true and list is new, subscription starts as pending. Existing lists use their own double opt-in setting. Default: false
sourceNoAttribution source: form, api, import, manual. Default: api
metadataNoArbitrary JSON merged into contact metadata

How it works

  1. Upserts contact by (tenant_id, email). Merges name, tags, and metadata into the existing contact record.
  2. Resolves list by slug. If the list doesn't exist, auto-creates it with type: newsletter and the requested doubleOptIn setting.
  3. Subscribes the contact to the list. Idempotent - skips if already subscribed.
  4. Sends email (if subject is provided) via the _default template. Dedupe key: capture:{list}:{email} prevents duplicate confirmation sends.
  5. Returns a combined result with contact, list, subscription, and email status.

Edge cases

  • Already subscribed: returns success with current subscription status. Still sends email if subject is provided (unless deduped).
  • Suppressed contact: contact and list operations succeed, but emailStatus returns "blocked".
  • List exists with different doubleOptIn: uses the list's existing setting, ignores the request's doubleOptIn flag.
  • Invalid email: returns 400 with validation error.

CLI reference

molted capture [options]

Options:
  --email <email>       Recipient email address (required)
  --list <list>         List slug (required)
  --subject <subject>   Confirmation email subject
  --body <body>         Email HTML body
  --text <text>         Email plaintext body
  --name <name>         Contact display name
  --tags <tags>         Comma-separated tags
  --double-opt-in       Require double opt-in
  --source <source>     Attribution source (default: api)
  --metadata <json>     Arbitrary JSON metadata