Product-triggered outbound. CSV you already have, or POST /api/enroll when the product fires. Sequences draft with your LLM key and leave from SMTP you own. v1 does not require a Bearer API key — use a session cookie or the optional workspace header.
No scraperNo LinkedIn automationNo owned prospect databaseNo inbox warmup as the productNo guaranteed inbox
POST /api/enroll
JSON body. email and provenance.source are required. sequenceId is an optional UUID — omit it to use the workspace default sequence. Tags merge onto the contact.
200 returns { ok, enrollmentId, contactId, sequenceId, status, idempotent }. Invalid JSON or payload is 400. If CostSlice reports that tenant unprofitable, the response is 409 with Paused — tenant looks unprofitable in CostSlice. A thin tenant stays paused until hitl.approve is approve. Forcing an unprofitable tenant requires hitl.approve of force and an actor. Same-event retries that already enrolled skip this check.
Workspace (no Bearer key in v0)
Auth is soft. There is no API key header yet. Resolution order:
Signed-in session cookie, if present.
Optional header x-enrollmill-workspace (email). Looks up an existing workspace — it does not create a user.
Otherwise the first existing user in the database. No fallback mint.
Idempotency
When provenance.eventId is set, retries with the same workspace + event return the existing enrollment and idempotent: true. Without an event id, the key is workspace + email + sequence + source.
Stop on reply, bounce, or unsubscribe
These are not log-only stubs. A matching contact's latest enrollment becomes replied, bounced, or unsubscribed. Queued send jobs for that enrollment are marked stopped. The send worker refuses further sends. Reply timeline entries store the reply text.
Bounce and unsubscribe return { ok: true, recorded: true, stopped, contactId, enrollmentId }. Reply is classified as inbound: the sequence stops, then a summary plus two draft variants land on /approvals. Nothing sends until a human approves.
POST /api/webhooks/inbound
Resend inbound (Media Yard dogfood). Accepts Resend email.received JSON or a simple { from, to, subject, text, messageId } body. Idempotent on workspace + Message-ID. Classify:
reply — stop the sequence, then Approvals pending. BYO LLM writes the summary plus Short / Helpful drafts when a key is present; otherwise a stub summary and a manual composer. Never auto-send.
bounce / unsub — stop only. No AI drafts.
other — timeline only. v1 drafts are reply-only.
curl -s -X POST $APP_URL/api/webhooks/inbound \
-H 'content-type: application/json' \
-d '{
"from": "casey@example.com",
"to": "you@yourproduct.com",
"subject": "Re: your trial is live",
"text": "not now — maybe later",
"messageId": "<unique@example.com>"
}'
If RESEND_WEBHOOK_SECRET / inbound env is missing, the route still accepts JSON and signed-in /approvals can simulate a reply. IMAP poll is out of v1. No Slack notify, no hosted LLM, no LinkedIn or SMS.
GET /api/health
curl -s $APP_URL/api/health
# {"ok":true}
CSV or enroll API
Both paths are first-class. Import a file you already have, or enroll on provenance.eventId.
Mill recipes
Media Yard mills enroll through the same API external customers get.
CostPerJob
Job closed → collection
A closed job on CostPerJob enrolls the customer into a receipt and review sequence on your domain.
LLM keys and SMTP passwords are stored encrypted with AUTH_SECRET. Add them in Account → Secrets after sign-in. The public homepage does not walk the wizard.
Domain and inbox checklist
Mail should leave on a domain you control. Tick these yourself — Enrollmill does not auto-verify DNS and does not warm inboxes.
SPF
A TXT record that says which mail servers may send as you.
v=spf1 include:your-smtp-host -all
DKIM
A cryptographic signature so receivers can tell the message really came from your domain.
Add the CNAME or TXT selector your inbox host issued (often s1._domainkey).
DMARC
A policy that tells receivers what to do if SPF or DKIM fail. Start gentle, then tighten.
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
Anti-claims
We will not sell a scrape, a LinkedIn farm, an owned prospect database, inbox warmup as the hero feature, or a guaranteed inbox. Enrollmill enrolls people your product already knows, on the customer's reputation.
Media Yard LLC · PO Box 73, Pennsauken, NJ 08110 · Terms · Privacy · Support